From 7dd8c10697c6a7cdc10a07b75a599748ceb72cd2 Mon Sep 17 00:00:00 2001 From: Matvey-Kuk Date: Mon, 18 Aug 2025 15:04:36 +0100 Subject: [PATCH] Add MCP Catalog Trust Score badge --- README.md | 2 + .../kubernetes-mcp-server-github-copilot.jpg | Bin 0 -> 383595 bytes docs 2/images/vibe-coding.jpg | Bin 0 -> 194354 bytes .../package.json | 11 + .../package.json | 11 + pkg 2/config/config.go | 51 + pkg 2/config/config_test.go | 156 +++ pkg 2/helm/helm.go | 142 +++ pkg 2/http/authorization.go | 179 +++ pkg 2/http/authorization_test.go | 220 ++++ pkg 2/http/http.go | 119 ++ pkg 2/http/http_test.go | 515 ++++++++ pkg 2/http/middleware.go | 66 ++ pkg 2/kubernetes/accesscontrol.go | 40 + pkg 2/kubernetes/accesscontrol_clientset.go | 141 +++ pkg 2/kubernetes/accesscontrol_restmapper.go | 80 ++ pkg 2/kubernetes/configuration.go | 115 ++ pkg 2/kubernetes/configuration_test.go | 155 +++ pkg 2/kubernetes/events.go | 51 + pkg 2/kubernetes/impersonate_roundtripper.go | 17 + pkg 2/kubernetes/kubernetes.go | 214 ++++ pkg 2/kubernetes/kubernetes_test.go | 316 +++++ pkg 2/kubernetes/namespaces.go | 19 + pkg 2/kubernetes/openshift.go | 16 + pkg 2/kubernetes/pods.go | 251 ++++ pkg 2/kubernetes/resources.go | 209 ++++ pkg 2/kubernetes/token.go | 39 + pkg 2/mcp/common_test.go | 421 +++++++ pkg 2/mcp/configuration.go | 46 + pkg 2/mcp/configuration_test.go | 178 +++ pkg 2/mcp/events.go | 49 + pkg 2/mcp/events_test.go | 115 ++ pkg 2/mcp/helm.go | 118 ++ pkg 2/mcp/helm_test.go | 264 +++++ pkg 2/mcp/mcp.go | 212 ++++ pkg 2/mcp/mcp_test.go | 126 ++ pkg 2/mcp/mcp_tools_test.go | 179 +++ pkg 2/mcp/mock_server_test.go | 151 +++ pkg 2/mcp/namespaces.go | 62 + pkg 2/mcp/namespaces_test.go | 174 +++ pkg 2/mcp/pods.go | 330 ++++++ pkg 2/mcp/pods_exec_test.go | 126 ++ pkg 2/mcp/pods_test.go | 1051 +++++++++++++++++ pkg 2/mcp/pods_top_test.go | 248 ++++ pkg 2/mcp/profiles.go | 54 + pkg 2/mcp/profiles_test.go | 88 ++ pkg 2/mcp/resources.go | 258 ++++ pkg 2/mcp/resources_test.go | 791 +++++++++++++ .../mcp/testdata/helm-chart-no-op/Chart.yaml | 3 + .../mcp/testdata/helm-chart-secret/Chart.yaml | 5 + .../helm-chart-secret/templates/secret.yaml | 12 + pkg 2/output/output.go | 127 ++ pkg 2/output/output_test.go | 32 + pkg 2/version/version.go | 6 + 54 files changed, 8361 insertions(+) create mode 100755 docs 2/images/kubernetes-mcp-server-github-copilot.jpg create mode 100644 docs 2/images/vibe-coding.jpg create mode 100644 npm 2/kubernetes-mcp-server-windows-amd64/package.json create mode 100644 npm 2/kubernetes-mcp-server-windows-arm64/package.json create mode 100644 pkg 2/config/config.go create mode 100644 pkg 2/config/config_test.go create mode 100644 pkg 2/helm/helm.go create mode 100644 pkg 2/http/authorization.go create mode 100644 pkg 2/http/authorization_test.go create mode 100644 pkg 2/http/http.go create mode 100644 pkg 2/http/http_test.go create mode 100644 pkg 2/http/middleware.go create mode 100644 pkg 2/kubernetes/accesscontrol.go create mode 100644 pkg 2/kubernetes/accesscontrol_clientset.go create mode 100644 pkg 2/kubernetes/accesscontrol_restmapper.go create mode 100644 pkg 2/kubernetes/configuration.go create mode 100644 pkg 2/kubernetes/configuration_test.go create mode 100644 pkg 2/kubernetes/events.go create mode 100644 pkg 2/kubernetes/impersonate_roundtripper.go create mode 100644 pkg 2/kubernetes/kubernetes.go create mode 100644 pkg 2/kubernetes/kubernetes_test.go create mode 100644 pkg 2/kubernetes/namespaces.go create mode 100644 pkg 2/kubernetes/openshift.go create mode 100644 pkg 2/kubernetes/pods.go create mode 100644 pkg 2/kubernetes/resources.go create mode 100644 pkg 2/kubernetes/token.go create mode 100644 pkg 2/mcp/common_test.go create mode 100644 pkg 2/mcp/configuration.go create mode 100644 pkg 2/mcp/configuration_test.go create mode 100644 pkg 2/mcp/events.go create mode 100644 pkg 2/mcp/events_test.go create mode 100644 pkg 2/mcp/helm.go create mode 100644 pkg 2/mcp/helm_test.go create mode 100644 pkg 2/mcp/mcp.go create mode 100644 pkg 2/mcp/mcp_test.go create mode 100644 pkg 2/mcp/mcp_tools_test.go create mode 100644 pkg 2/mcp/mock_server_test.go create mode 100644 pkg 2/mcp/namespaces.go create mode 100644 pkg 2/mcp/namespaces_test.go create mode 100644 pkg 2/mcp/pods.go create mode 100644 pkg 2/mcp/pods_exec_test.go create mode 100644 pkg 2/mcp/pods_test.go create mode 100644 pkg 2/mcp/pods_top_test.go create mode 100644 pkg 2/mcp/profiles.go create mode 100644 pkg 2/mcp/profiles_test.go create mode 100644 pkg 2/mcp/resources.go create mode 100644 pkg 2/mcp/resources_test.go create mode 100644 pkg 2/mcp/testdata/helm-chart-no-op/Chart.yaml create mode 100644 pkg 2/mcp/testdata/helm-chart-secret/Chart.yaml create mode 100644 pkg 2/mcp/testdata/helm-chart-secret/templates/secret.yaml create mode 100644 pkg 2/output/output.go create mode 100644 pkg 2/output/output_test.go create mode 100644 pkg 2/version/version.go diff --git a/README.md b/README.md index 744a4d73..104e7e79 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/containers/kubernetes-mcp-server?sort=semver)](https://github.com/containers/kubernetes-mcp-server/releases/latest) [![Build](https://github.com/containers/kubernetes-mcp-server/actions/workflows/build.yaml/badge.svg)](https://github.com/containers/kubernetes-mcp-server/actions/workflows/build.yaml) +[![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/manusa/kubernetes-mcp-server)](https://archestra.ai/mcp-catalog/manusa__kubernetes-mcp-server) + [✨ Features](#features) | [🚀 Getting Started](#getting-started) | [🎥 Demos](#demos) | [⚙️ Configuration](#configuration) | [🛠️ Tools](#tools) | [🧑‍💻 Development](#development) https://github.com/user-attachments/assets/be2b67b3-fc1c-4d11-ae46-93deba8ed98e diff --git a/docs 2/images/kubernetes-mcp-server-github-copilot.jpg b/docs 2/images/kubernetes-mcp-server-github-copilot.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f27094a220750a1dd243de7ae47bcc86b1f4e500 GIT binary patch literal 383595 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𝔜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�{)!&dY|#23KfglxDc#rJbU&b3nG(i{YaDBa$rZvq5kbu{&K3rai_mae?vz26BsgmZ~1iSl(<;L zah$CcyCMKXeGatQrV1R|m!_uLJOwhud|YIu^WnZ<)jbDJL4_cOSI$~?Cz0{D!$%h@ zozkBfwHaQB;?wz#Im;*&5b$_c_Xw$9FQY1Bcp)uWNDn3Eo~)Bm7;p9*|5?HCc@+N} zJsTNArLmkuXch-B8B3`VQa}1-CD!oP=^7%yT#_cG-|>tv85q3nwMKEIf)hVt?`9MT zR%UW-6i+m{B5Tt)rdnsZ0r91I`Z^VPsx%pC^Co5^{Y~qqspUgY=l^#O>K)zIT%hk2 zIj!?hU4T7trl6l(LeDXe^u?w=X7TmM7R|0p2dFTUFOq%M)R`s53ymJ%8)kQCcR9Jo z2dN7{2|z9`LsKK}VnYy!RK^I+VuuZr76?7+@qRMl{}kqu@c_+b6bgD1A#gepH!$*x zZ(cIg40Pe92|Us4Nx~gTm>esSa&D7$Iur^#6`75EN~xP>GCvO^M1&xc>a4>HrQkz7 zRz7}YQj#jdH`EvVItqXYR2DhUjH|t>bVT50 zexX?rwzH3=4s$1JuN_Q9!$U!dIs-T@EklW%>HK$Jk~BCHo)`1(#A;gA*Vv@+G^9o zLF9f zUC1slIJ2({^UlnA&A?!{wis;JnitvkD1Ey2zbzc1U_%alY?Z4xEfu~|0kKir(;kLx z!RD7$Hxui43Z$f;1R9$dSm}dqLncze;hh>vU>{@C_r_%lO3AA7+9uC^pS%L&r|b-Q z)MPK*jO!r!W)YouOHYa}A$ZT^B#DlCOM`iGXQhnwubeg%0Gr63PZ~i$W9At zm;jz8h|&j=z_ne`D>v$gb`*=ZYia8*yof;;cCr0?zl|cb3hzI?EPl)KC}Q@TxI4@V zgh;Vk0WP`Q^u?q-v}LiXBJw?npfH0xVf#jMM0`;9hh!^c5oGU(>q{C|ncT*IR(g&JF2&whQ1H~h zYS`{ebW$g)DW#4A?_uDvXpk`i;IK;92x6}QQCT*?mzI-3c)`(NUxQ;o0JR_*jU05% zq72&o_m|NQJ-DFi2fIL4I%%)E60Sb*Br5v>|1+c7GnxyM^-4kK!n9LAIzlwy-<`4_ zF$~;2pHS;-2xwSe+wrT_>;2X(6Uf>YUUkbOt?MuN3-H~~e*w$ai|{(&v(h*7fd}%iPw7qRLWCm(_(@i|<|Ty{QB4y~5_TLG@0d zGXwQiq~&b+ez%(APfT``Rv!ifG%*4nO*|3yVdQ%{fh_B!-Whqq2lIyWHsCK99J#-nRs1-ODa7Z-ezz?YUs9^hHS^QkJ`%$?jBkdOmU zPW6JSCnk}=#DTO@v;+%d&~5`#j!Ud-bp%jv03bpm1E|^`qM9#DDE&`6r6h)LnJ@$n zZipqV)1GUR<^@kdfYaa+pR`oa`6RrzVR}}n6;1)}t8czGeeTCRMMKl2nTTY@%x%=fxRY@L@RA$99w&ABwoLSaDfgyZGtD zs7k|+_%;}^n@j~Ih0sW(y;!DYZ8Vx-)QS>i(^7ghT{MnBM<1|@zLU279Byk{63^3R zf|A1vzpY!L+SW^cd$_p>+-x&%wbDle1%XJje6veY7Xm82o1A%`{#r)>a09$aOPg#^ za5T&|0$k@Q8tEE{iG)URLyOBw;QTY~7S|C<9>KDw06Eimo@}DKhsfobj6yCV#7xxT z=yng2cXEGz?(OW!bTr-Rx8RMq`Gcm6aV7h_rtAmiYKr>RN;tdySvd?G4-y+8HHdKp zggxSkY+-)QG&3jWn@a#cy-$P-WHgFzdl=v$uD_)pXk_+rMaOO#5S0*amO_PoIyd&d zU@NMuHh*J>>_MNJd_D--g?r|L%J;XX0$^62ePWqAlXh);Ut|1%jzbp`LW%tGwc}8X zU~W@yPHJloJdA<8M|c;Y`)3g3b!;6c~;MYTOKw^IjafwHWW zJIh4sf~c2VfmX75=Nb6?GWbq~cDkrQg{wQ2D+N4yTT>Dym3Wg4a40P)J_fbgZEQ(3 zA8WzsrTr#7tY|i6`L%V|Qaj73(r7TXxVsK{$NpD+vv%%*Uz5$&k>CyYBnJ}`9r`Gu z>18+5hRCp|HmQ@(WF<5Rd&u)03qy`dOvQ8s2}c*1Z*21hlj?=5fcDL!)9(7g5y0(# zg|RaVI?rqbc08BZM!~AyhzX49|6ab&j+#iGkO+a4rp}$WaReanx1S9Jr^Wi6TITxs zXRb$C)aHF@2rw~BE8|1vl*AlCz|YKk12>&F^@7Y;yVlql=LMim>JoTt^eoHTw7ECh zL`xZqqOWK}cP6KXCwJ>>tPDTC!%yHdcoRq8Wdp=wRkFf6xYNgZ3qyFD0x=Ps)WJ#( zNDKx3?3c)yEHn2J6XPRhrH@Ty5PJs%%|{-o_?$xuzHcR&txqUxO!SH{`%M)-+< zzz~!3R#k@`GCG6y{1Cu+Z1|B*R9Ab5Z`<=IW2$Qlx=H;bB1;3VYqhl1BUR!#(Y}m`Ggg#OEsl8Vc;e5bd0y5N) zkZAQu5(k8)BccU};YKFxeVkk-QnT(EEud}i z6Po{E$y7Ua%;`){Bguj&Qh9FihC%g$#2&Cl?s4z{l1^s@`_J5vnE>GBynw$q;~ZtH}*EfPh1 zY(po}3siCKw4I5b;fHPq*YlgVe@Q7MH1Zc@vDj5hzg{kJjlBPQ#d|Nj(z$ZK8BJ;B z0lbM57^8Hsuf8GaP{%V0pbRZEuQ&SUUr4seS?h@4zh7lHY9l1;@5z^ytaWXaF|xy- zAVs#}A0XO%k2DbTypYs+wv1suZV_TtV5Re%9R>w)rQLY|u=fE^fmIqn(sh51khDGv z2MF`9%GkFG`)!+3%UvO?Mn%EHAeW;sAhw3D1QJ0`?^{^7_{D3oGVXxZEenpgEagLz z-~9&pT$tP*0JzsagJ-xdU*-(dAfPK8EZE>@ zFhS_bZ_C9gS}q9qC#3)P*UL8$WLYP+_}=U$(54+f89YZ}_k^?=4rNV(K|9>)RSY?i z+Xz01ObMx~3=Dv+a2LZ{a7&DgjumTOipqM&;ad^_XX=3U^+iWjFC0Qf#R}9s#1kVU zK*2uK^kC2XW!JQlJG=oGj5^B}pADasbl>JfJmoi$;nMejJ_)=`B>|Qswv5?#--3Y2 z;|}NU=37QPF`fCmHNi?FAfw80KtJ){U$nAE%QC*cczJEOIG31BW?bb|84ZjFR~pR? zCYL?2sy5tL3^bP;jiA>Ff6sZDQBsz1Z64CH(I=!CYn8 z$K+svMfr0n-#CO}wkCzw5jm4RGFk!6hqjdo7yyv#`|bQiDu<*5@hYWkvr@gjSk&f(p)9$ZlgM@eA zS_5yw`g0{wJ*1k?zZ$yH{b=CYMxi{F*GGOqAC9$yBV{riDe8Q`Ub7}}JfF%K?(gzT zPP6A3_zh&4QmL$FnKCzZq@X)$?V75*n82W&>Rs_0CV+SX>|tZbW%9ZKZwv5SMs6~c>;cT01 zAy6^xDw7b>ys06U)9MyLGBUV<5CBsA`NgrGCg+Cp-u%k?B_Dv}R&$aHHq6FLz6``$kT?D|8MBw+cYb)eE(_UH@VKt3c|X|H&kZI+r8!M>l02zIDp9w zz2I)lFaU}lp4&;G49c7$uNs06JWZgF;EURDVPl&*DS0t) ztS2XdG?K73@y@q+6zHmbWaX=eO7uVo@|NfxQC+>&COIu#x1|_tE-eU%>(U_@z3`ow zwnZD8HqXj4L}OdTF{J(oC39w^VEe3mXS({$5gX^_Ub+5;=A$l$P?bPPL-evO!){`U z_(r|@^oYgzGe-PcvVlC6!Dea6?b{+!)gqq5au&e>6${YpY=L}l?{eG67VMS(VQ_?& z1_1GwjIXg7|4p+%1R%u(d(O2%E6qwL-h7XIa3QMT3@QBM+?2TS!G*B&HNIK zS-UP%Nw1mgxZ_Z>3x}lA`Ftorvt*avvXj8en`EOY``~^dWK=tq$d-fjp~#pZ>i?(d zz2n*H|NsBKOIy(z4ILt>f1Fg#o{)^@%E>Xb2p zjV~uaG(XE*$VC_?qTg!6Y_FPCwaPvwOPyn?RCE=l;Nd~0$TT`+}yEb=PKaK2nBuTCdR z9B&#W=|z~448tj5+F|-YhP~DllqeTJqz5G$E}T4X;24kqdl?ETRX~VL!xRz+C7VZx zav78h;<}h{!ZhLo!IspFXI$VZrshCFKmxvmT^oPS5~k-rhJvjqY%Pi$Uv$li&TTA6 zgd0Zp7@Y2mg`Q4e2|}M5<IC^Lh| ziFC2B{F4%P5#hZ2VP3JFy=7iTaU8mXFW+ORtUnpfldVl8!(1?lQ)sX<4BxjZ@gzd{ zI6lAE>D*9J$$!V3k;wyG11kU#TlZ@Z^CDQ5(qAu^47!~3DOfS{^36L&iUJU(((?mSp)z($O^bbA^gv%~=kHejnN z*M55qs!vTFXC!toFXQRBmUZ8_F02r`Fp+64CYlWN^$bKc-*TLMX~u4Gz+kaLGuDBe z1YGowiC_fBsNtF&oXD|MU|)0hv?I}EW5Vt2vA}lCV|BXk)c{>L{iq3R_WM<^;Lrs* zmL*?Y&H~i7m^+-KqkkG0iz{>Cmbvi-QWqRzg-&uvizg}iy0<4TBVYlE(lEj>Fa8>t z%IJjI?}Dkrs->#H5CV655ZDQvm-pkP;X{2KL(O3jQW{h@JQ4{1O`LZoxU#jlgcEUz zWU&_Z2>JcMz<6KY%V?nYr;iU+P=#ccVd!9W*7KsyP#@i=24SRi1OBo3)XSfzP=e$nN{4A}}0!29q+iQn$T7q&t?OzEBrHF6l z>2^|(L@6mOXN!*Na+b197UvJM71xIAB+i1sa;*?%d5!_vmO7IEi0+T$1501Fu=t7t z@qKW|`GNN1*kPxb+=8uho(wL0=)=pI^ZU$SFN>Wjkjn8wm5>SRZkf|Vh zeKhFFxt>%w0V^slX~$vsh|++YSnPR8?_+aDxg~re>_NFEujEPe@ zcovy=WXfrlWS?vXVBN96v+7aw1*n&gSm%@Q_l$+9bnHFAMT_SEo2eyJ--W4@UdW8- z5BVqUYyq8^6+{7XQT%i`FzE$^Vrf(oSwcWgEJ~vlbS@NH{3s*h1;?Ez1wg3UL;(Fv z7iksGat9O!FBG8ij;pw{P}9`ev$;L)#`)Sf(!jj7moyhUhd4gV<8%R;hKp{_gV3V} z$uwPKxA+{y1+`%+7>m$O1*nvQBLch`MVhSJlY}_1WN}yq2d(rKE2Y4ao3Y|M3r%ic z>Y>`pu!=z!Z9TOtp{BS*%-c&_9#8?WiUlY7&-65X<`?Qlzf~%pA1zPRaH;`WpekeiOH@Ga=C%t zCr0p)Sa6lgR%vxP+IIxKtSV;jRvWGsx(7$}r%xRx>L{a!PFvLT2T9}Y}c zI#=+FxC^Bad$r3EJf_mzNeU}+UE!)1w4WDoGGJDZ0E<%AIcK1z_0orhD$ta$6u~T4 zys;it{tK|tU)_+sq5!kxdHdzm03X(s1X;R0NNoPLuBFkJ4*~<247k22z?`)w3tf&@e-sU-6&cA~#@qat`lmdAqo!sICH6NLAAo z5~bE&fMwRo>gEhZ(b@4i7%<0Jw^Kb@7I!<^VTecD^N!YK8429d+u@rthv*b##hg=x zM@`y5_T&eIj)6*;m@p6s*gnrhez1VYN10L2!pI^cc(%v|HK$I7>ebB_6l@2_8EB(Q zHpdXOdz|%BTVaHmC@tipjEQrpU^*L&;|06MD%!f*F>X(vD?H5v8(=Tum^o!UEo(+P z#{BHELKsbs1Lx@_0f^jhI)=%H36eR}_I*)9hV5kams?a|2(1Xe&vErYIO6kLE?gIY zfG%JLCT1i}giG-*pq3)e2OK^_c$AB?6{f!~ZY(0+LSn2qAUl{-(|1}q>eg^Ec0#VA z?$cB@8X-p2f6C>mU7(*%;M=FrK8l=ur8Qv8v*~??n8bKruGAQ!yBShf0Kl|{qYf`M zRrr97g`nD=!9r*-oXVxA#ZS)*;I|S~f2nf8KknDM)23C6li=)Fh8R8%S2bp==kjfjWg<$PG#c z)L_MExm4C=@k)3 zR5U%u$O;!@1Wg!h_>{F+022QG`)t$Hw@sR;7?=uWSjf>mJAn^eK>;VF^IBL&Upy&R z=vwI6qB5Je1hCdggzN@aH?M_&Vu3ifK{H!IkNkK5d(qa)H}fr2CrmVwIXG$vR+J92 zs^bqABwr&@o*2X;Z4KEk0CSe|Nrabgg%U@ShfyadDr(CKx9Avp)tbkP7gnsmY5jHj zYXGW{=USg2RUTmrDAoVVk^7x|Hx6FC$zNuWxfzMRZ`oYeiVW= z{lsYR%hP)}SpU27s$Od9_(u;26*k}XfKS^4g!N}d%VK*tVfT_v3SGr(t23JAeJqM3 za5Sa(NG!}9PmSkZu7W^b2}zyBAY;728A5n{-Tq>Nf21nQ|2 zHHeT>cpn9%^~;7av|SB7ctXDy>7RQ`5xM{%!e~Q9h2NAd`QA^Qk1({+@Vix20HHL? z9LBl^2(!_Tr&2R0_L#^eS1KvQGqJA7!I2(2a3~kW6pGa5II>DEzFgJ%et4USPZx8g z2uXqB=}5vwho>+ePo>-AWtMlL{ioBM=nO4+Ob68HgYW^__Z&&hBl$eKxMun_cLMcu7zrj@$kRJyAebRu zcAE(Wa$OK5FvPV`geaW569Uqjf@vW!bd%E~T9cT_h(zX{Cu-uH*a=CmdWSQT;81f( zQ@AY9VW(Ww1|&Wg^oWH}FhU#mz8L2CHaB}}0rOA}K3WMtlTntY;nLh? zG~@7QDA7;QKALKoE~<+I_@-&iwHJ_e^W(`pYl%fPXty_Xv#@3_-R%T3n`tQ}|%v*j41Ub<6bU6$RY+c`}De zTCmP!{u~+ytjSLN>KZCpq3iD_fa6PD@9Hy!MJQmhI1(o=4#dj?(0Z^wEZIl2TS*D7$i9Pnp->7E|6AzH zC_aLDj;(w475xl34(z*Bei3Vmdo-{n6pCn;1T_0FDkfe1QR<~Fb>j&*cYFCN%rXl> z7;y~Hd@gbsC7UJ+3ji3LkEkMv5O{1ZONzU5D!oLC3D%mC6v2;|UoMj%Dac8<0bK_S z2N7BeJ;(7lMFpDE#Q_T=whqLLLfkYz9{T!6`P;iKGL|5GnfJ}22`-{}ct>6VptnRx zvYAL2j`r3{a1hE+=oEx0#N8eNQ3z)SRS}+;>G;#pw1~6cWWClAm!qgIN5MYdF8Uj4 zz5)6&*n3(7%;t9s_Gl}ve*QsAy82tHy)yTcleQawCQtDE?|&!$ck0CRDqcnD#y=+< z2g3I{k~+1b7?#6e16mX8d9f)%D32ZC&?V*^VRa;0T_p|i)FwEj~>4pghyCB z%2j`+03O`&c#3I_5%~!Yz({EM-}567q>9Q(wJacaLJkVu*9^GKC=t zFgXt1HlV8Qcdq`e8dI{3?sC;a6>-P}m8N4!$kf)%1bh0v-zC6_Sptd>$u*?qxm4gx zK=O*$7nKe9N>`*Nr}~TPFjJwWq#IO8sAvxpP33Z96bzI}Rm-9UwOP&}S$$dk`+7P& zY<-H+ds-$vW*b9W>DV;r3f!I2i1;aR&*_;)b$3Kl{88+i#j;PzArkd7XUY4QmNdX~ z8pS_N5?+6f-)ivswjiQ3WEu${qKH006pmQL-y6m{7hac^F{te}P$g8S`H(FMGNG)_ z@Lgx=4SvMx3YanRyMUm21yC*;X5)oC({bXuFIk%rB7UTW`MTO7ix19M@GKYfV`XS( zpBrc0HI~LmOg55)$wfrmlm_oX^tJUI4_lJXSWf!L!sRV$os!JCddL;JPP|Ob63Eb} zYrPb$3}a)QHqu|#T$BpE^8JEZv6q2t83A9{r|pzIX?YSH2G&gCCt6T0z%!H*lReEq z($|%gCO0qPL+$hA66;0@`Xogqm_>Q2uIu`AF6?2g3f+~&Yj&N7Vr}pQw z3Wg&@Y^7dDKYsIuTz1Vi05zU=rQ<1gv3aO|3;T|?CoSxWdFtA8C{qeBYjC2}swSg> z8lGw+Kdp}tylfZRtk}HyMRSVLv<};Sk+M*Y*IK_WKP{^MX-a~8uI&b;EnNU$!DQQ2R zR6P@WcVnXh?bg@9Xr%5){N0efp!x9AbwdZfIKuBYY`z%cmTgbUd0KBy&XP|+5;-H6 z$bhw_(z8k`6-c-DAW%i3eb*gAZoZ^@9#q6gW07J&nK{i}lv&(gRo-0*VM@p587IUd`AfaT{4+!>m;z>bT;tua+YmL>+zhwUlg#P)vMk7M`Od_^G&;oJJsU#cgxow!x$9Kq&Cr< zFlm6b>tSu8i@HooOc98H(WCGsYqVX?*+5xM3f9c!T#)kg zw4-6?*#oeW)Tsb5_nD%ZO3nZ6-_4&GEwQ+l_r3aGY~|DXE6->8V}5+Mj%u1c^LTVu zsKb2VSEy%w<$XLvlc_ddXvLS)bZ96- zI4(vH>Kbl8X^-EMaFP~`7+jK0A;)!j#uWR=F$cOdW7wWkoI(YVYzDvX%O1AxyG1sY zhrn+&0+g_B1+#7zYi^u!Sx>ZA7y2CWcKeWelm*~xkR`3dQ4|uK$O1rkCQ3B=8d3&s zNFyK_5yLMR&K`gmc}EXSKtgCKCiOZm_wxRWk^n7L?fhyGimqoyw1`SGG<1TV4kw(n zVZEO)K&yE%SfjA_X+}$=$k+kSrWf!nZ+^ zMJ~)q@BAmR4)jc8Q=s!i&~?^tce|c_cdm+`c5^o+my)&vkC!`rjL*dud&Mx{dR-rj z*}z=gesR}%KgH6)+M!3{>iDnjvVf}{f&DM4S6V5(L((Uc^=)0Z`fHKA8N9Ndn2z-P z{c5gIrW`tnbi1b*Z~oUyRdOL0k|MnGEMtRDSD}$=)~KAup`Zi(jA+hYXx`PxglM*7d-X; z8TTXxQhsRJQL?EER6ddl=-KD*N#?<_`AB^D?!&*wUnZUFy^6!S z1ES?zC%OQfY$eI2tD8<&low=VR1=6CrVyI1z&`lApj@Y8Pb5dt&NyeNXM!e5yB5G& zTF123rxCGYwiGwm^rNAR1WbXRiOXuCTsY%>wjIz495iJE-lTRK!b_P;+f!fGErx0@ zo2D7(+t5C51S!yUzF%xQtr3HH|Nah!4ivGlpdu0R(xz+jbo%MaOk4R2n$%a@a5Z!s|R{N)m(JzVN$o`+I> zWH^=He7qoqKwC!=2d9bC`X;rx+0&$C-2}Zrn~D_t-ins^iIFt22o`lY-99B6zLw#woj)?!58K5$dVXc11(}lr8FBVR zy3IiF{qADJ&Wido+zJ(4-XWIEQwWIEO=Y?};1*JneYDvEH&T!^T|jzUjP!JBuP!U| zX~x`JGBwOLaepwW{LJx9N>Ip7=ADT~H}tz(H7%@Esj@WdX9D|#f@Sr)HQV;S7{9mq zs!}vp8ymH62&*m}LC`Ss?Z!FNK6X~uHR`XDNL|8y&GYq~1cfEJk<8cU({=3}OOz()wGs?S-J|IX9Fi%Aer+nG#sSZkN zYt)=~A9ZLSpeJ*ZJ82dl(%9N-CwqPztyDf3Om81%%~fbV+G#Ir{Z;zDl@%4{8T^b6 zCH7FFM)LXDlCaLMJeg302V}*!S<+pozruP5HeG=v-VnkbSH~yDX&n`PdfZZ?#K86R=cq4HI^Cj=Y&msjQds)u@@bj-n(YG zn2*nw9u((sQx(M@66c?qaT|DA@l^qw8m@V5+3cwlnuWOeUgj%t z9Lj<;=W@&Ex-vdLvoDD!+5c?YrG}OsCA7HaM8SdN=U$a?UrjBJ$_=ZU7H1ra(wD;h z{wQs~zJGmZo2sGdHqhA7(O=T@96k+9KCE!(Wf_60OG!`XWEQsHv~?%$R2ynin&q)h zx*~eoq{CXQySR+I7+c#-HIga@0Uznqd(mg|jEs3BA-pRKIq0VEefnO5TXq$FwYOZQUb$QH3f zPRK{e9dH6Vd_;w-$fuyp>3D?wAGR@Kw4g)ZE>A7A&em(osiA`?sv{D^kj}QZR3LIf zi>(&tF7951uLpEgYy~#&x8lx6S)|>QN_TZjP=HYwOcB;y!?U^3sZv$5;%}$=QTk!R zWOSXAV>INd1?$jIq+);)nG+ig)uDc~ia)(%c6LA0cn#q|1~dSMht*IoZN0L&OE&~Q zSQ7%aJ1+(0_a5dWq^40!5q&J4fbFUFD)DIl#q`$vD{}dr+mtf;rp(vPZkt-i>+W?% zWA2URE)Q@7uoA3qYo$OeLLTm4;!|R`Qsa@1qEp?b_bBT%m!QF=V24|JRE+{XUAg#C z{J^yEz;Z$S>y-hDSJu;X*CenM+;dsDipItg*CK~|E86`a$BRX~=4ZUH$x1`3(l-hs zb5tRU#jCg?K>8@n72NthC-chrNt#6g?ZdTwtCTnaa>&uETxS|-abj!Q4T=thgr?ymf)QWphioyb?l`x{l00Y10QYm9KxG zT;b-aV_RlC9EM!B-t_RgT;x#{tdCDf%F+POfRUy0v7(o7tmhN%qt#9gAzm{oPP=?@ z{4W@}uhMh~nJko4nw83pf(4+LaxS18rktV$S1l@mke`>h+nAbP))sON=SWtNORJ>Kn(}G`|E$Nrs)NCjNI`3g(=CLR-&M{Sn=!zt#*t5&nR^wA7RJo{}{8zeh=*|6q+pu(A zvhVc*&8y~VQj%Jn{inwg?`wk9vk@8#>$1Z?XkgiZib--Qm6x%SE3ABz{YBAq`^VyR zRkI#!C+4}`PL%voVS+~aPY{`05K^Af^k?%P$Jjc##TduGW>gx2$2@)d zfNWGLNvJa}LFGCt{<-OrTPsY@iG~RN_gXJ&=vvZb2KDHU9W5&!f>|f7b!wKTdmd6G zi?@JuKW093!=hj+o+VJ3nW~_G-vu1)eR-VZkNz^wj}4{M%!SVUx2($fcjzr`KUIHt zVG`wbOL8aW;&PS7hd_93hthO#b^X((-+%Sa9g(N6+>LR^w0M36GW`ca)n2 zlBT{3|NLw6fNNJbyHDcOTmz&|`esYk`PpABH9xv13(xKxXA?Sn8~N0;`Nj{@FfCs~ zVs|$%Em2$3T)tL`DT5U`U$Oh>(e{Qw%5+8|MnK=^+~ieU_TpO1;~3(GU_LdzmFby z?hkeab9QffWQ%JezqY^dSipohS08IsUR|6rTYkvxnT>qf582WGp(4BQvNOeLY@XS1 zDDS`MpMte}@nzEaR!3FduRv!_qsG#wH?R38=;hbHZk$iBud3Wf-Mq5%PR;psA(puE zj(;KOz+_8kvhVY!Q;V9{O;AhIitSSZpsC+qe}p*vIU%9ycoRNwwiF$-_Le8N@Cx8!6s|&>WZey z;`D~|iWt|Y^mWfC3R#2Y>jyIqVZUjPAlj&Dw}t0>K&&Se}#=@YQ$|G{zlbfi>4~&V^gQ!<=SqHcBKlL$refj0kyXo zg)*tak}s*FUD!y~tf3qXUH$T5;a`we#u7{g?og_Us>&9Z*#7p$^3#1&8luw@%z*nf zOZz!a3#fd#rTc9b1#DhW+pNVbwNKO9837lYbC<0jCIxxa{K%u#NJ;TkCoad+&Rg*2 zOAPYQY<#X}+`s)Cpn7`+zGkrQCD?=&Yow)}FrYq*11OVGGNukP~9)5FjO{&z; z@+jTZjHfsi?D_@!yCqFGJl%6V#fh%2a}pmQ#p8B%zXs3AzW^m20=_%|^ds^i9ME&x z6JuM;nP4Y#>i=6q`AwD!7n(c+rEBLdc~p__Z=#l;1vmKJnw(+{=UX`Pbdn`J+~2_eY#I z*Ix(G0&RzmTz3;%0WEZ#io{|^Vo?1Dj7j1Av(FfVrQeTNn)r9-FrLTO3$Kr&11?Q` zt`07l`usn&{<>R&KgIwUP2aXh$Db4GjZKQv0$sPFf^0f8GW|`w4y=~nDYW|@U#;9w zt_!Yf|Gur>tbS_l*e~$erFYvNJwLDf6kqtY7j-1}b@^YTHw8)BOIOkzKc(4}^gYm= z{f;P3-l$wtX_OdS6m1}Uem)y=Je*f6(cJXw-hoEj_bbDF5-Rg)S0%oD%J#j^x@OgjgC#(#o9%?-iJpKiMvRL(myA7CMsEKm*mH5BGTV2{d(y9 z=Gfpz#n=&R=gwT=!G)C4{Vtk>1AU;l>se|ySH8hNXPiy{Bz>%N4#4prY=iuCmXU` zur}Ys>{u$*X^n1K>Iv`COH`c%?%S9m1Y3(bGuK|75q z$TlSlnI=2m8&Azos2~zEjXqo?;YZYxCo?8aa@=)5H(uLMg8Lrn>0Cbx>2_lM=Ww}x zyd?Yh2#~`~VP`}i?p6@KO!Wj7@-BBYXsWmb&;R=WtF@=WO+Ve{D4V|fHtF40CVnhN z?LHvXdGqzP9o1RC>&MjB1n5OEeyq1?E}H~pSx*NAv;{tzZC4?qi_4>bx3wdddYJQz6HGee;OPn8Z%^FbYa{<<*zR%tLao6`AfIjgn zx&WaC8a-~x+Rtu=YRZroxK0+^|JWqZtEk%eU%ly zVgHtXjBmnE`Tz34EBW~g-v-sx<}3=k&n^fAzq6dF*-wWZ6`ql<@c3Pc83ytPP5rco z)@BP1Vydjw&j`&`zqsP(x_dLxFI#&1J7!r*KJeM%25oNx#V*$aY)6QV2BY`N|McqC z?YA{;VXSTD6D030-w+wuA6yLlJFpA*xgT@X3U4lCb^OpAtJ;mfP#37Wa;RY>Iwi57 zy7|t0@k#2iu3;FD=dNfkz^JT{r4vx7_PuZ-0wPTXdLxWwu=cg!Gln2=_y{@;Y-@^{ za)ui#RA0}wSHAD^PdBFgQDf^t^_WzoVK1zW=*(KqYkQ{oF+h*8s)R!IqV{ShCzP&~ zEC~gV0F%L)6vj`knV^JjmCuXEJ~clMXgd##s`oTrE;U#?uG|-Z9i19+iasVob}$kVh6%B^1xbgwW07Ec5rObE<6r=b^=Feihr7cQ+pR z?`Jms2%CgiF?o!yH~?xHdHpDhxDQ(qNb~DYuHR-*xuhxuwRMzlF9?n^M_=qy4nVa| zCT1{|%c#5xa?7gn$$*ts9Hj!&K6sAhd=cNNOaRk119A`-bshKB-V|Cb+Redz5T$TI1qXwSa=J8EnrWMR#8x2?b3n z)n^MG8m*&z6`i4MjGcaAjQiXVSm&3lY7?r7`qo9?-`~|Vrd`t-589js-juo}m{omk z>6j{;391Wv4*zL~i>pGj_TvByPhr|!VDXrB7Pa=7bann=)8+m}Q+Ir8_nEZsi#qGL z+qqHzuj%5e0M&!V4&}gu*mSICp!|f7x=Or&hjnG<=Zq^|Ne^om=Z?P2|INF6*Z(ts zo%*E>3cWhL9{P%AnC~afuIaDr4!u1-M1ZqX_!3id9qj;P#QWBahOWmilrs1ThFHp` zQr+60rx*G52q$FzdEVGOU~!!z>?Jy!CrK_@MwC!dQ2bc)1^kd0NlZNa{dWWOG~Jl?s8I2U zxW!se^C^&JGC|d;sZCD@44)trv}JWYhaH@wPI5RLHwYj`%)WZ8S6S_@myS8x5j6L* zac8k+nElnSD)U8)Mb^)T6g%_Ao&O5n3IFxp^=}85Q%l!x(P|6`Z*ByNjMx6V+;*(7 zUS6{B3+pz2WdFH#&DZ9t=-$|$6Lm^yCHFTl)s)SkMW>}dCnWqNs(T;I{Ja%@BhVDs zhV8lR2wdBpQ(1o3Qk&dTIa6(uc8m_$Kk=i&yFbAXpnV_w-_Pf@mT&%dbaBrQtUa^DBXVMKRpWM~I=KVQQk^#IN3IFWsfa^XKnDrg>eBc|Hz0dyed-Ul{ z|AGm1as)WDvb#IK{_;K@_-Y@rB;Z^X^yJTpPwCaiptJ{FlE*q4KivJQY_i+`?k4ot z^iEkk%;OxlR=FKLYzYpZ9N17jxH|YW?hIlnO+vgPP;MzL>v5M!;=Mm7K{kHp}wq{3Z+lbFw6y6twKE&MsLv)1%taV$i) zWO0l-?EJbs`0HJjPk$#6x_yINJcivT9|Z0kRlAFBUkyAx_~mf(jq9-M8a7*ksMv-XJ2e;pSItg{#LSxIC=f4|)lnzyB4tgI{ z`GF!NxO-}>>Uv(wMbCqcWdrN@*L7y21v2g|>Vk(iro6?+ziH+S_ilvd8^lrW{JZOU zy$?RA>7~8dd1u$;xv5wE<{$LysfQbl_HjBA>l!7a&9ceSG}x*%e@eP(u#;7FnCO4u zM63>`d?a%w!?)Vl&7KU_)A9*JV!fmp3eSchRg+%9k^ufC{Yq(`k{r#dVyMR{^OW4G zmZhAlfs|0k!KUAZ>EDfkDdP>jFFU5s)M`Y1xX%|N`*D|Fr^TnrPyEF+|60K$#xY%^ zA~15)|Cax!pcebj>h7YiEi*4<`$=q&e|;L$*}OILZ+h%nMOwG$k#wWD@swTb@fg`p zNmE(l<=x8ls=eupc^)G_B^S+u20b2}7+H67eD%v@FEcw}7qRs@>x;{rxU%e6PYPse ze;X7iagb1VWVoCqw>u`ZXL40pd9vE&Qz89nqe*g~Nq?1WL&zTj(Z%4PT8TkEJ>}6^&uNvNesdz_h$B6^;Mfx*r(WxxE-L><%E40z~+k&-(nX zYc4E07hAkRxYyYnFpr!I-T$13|9Pj-eeg@;kiS7s{hJ6if!K!1_J+!;e>8D#HY;}@ zI%TcN?8I5SFSBNq#=ZElRZor1)OmQN1WnWi`EGmz-oWeFtZH=Y|9*mIE7IJrE^63h z`d!$Q*v=pKhZ?dI*%u^@sanv^%Jc#~V`HcD=QwOFah83tMI3&O(C+mz`YE7yNl}xV zBb{Y|L%g5oZ)lxBgCDeyPR#)K|Tq69*wJM@gxm$1fbqe0PYqw3pD zTTfmWrUx8wByQ)y48;YupUtX8%=#@hJt#47uyL5ydvWWNrkk?#NI+>P1C|~;)n$P| zQ+^?|%G>?87(0|y`wy!F_vztcg1BY|<`sA?#rY&azleesC zzT&QL_$WiBE3N)vw5CqO&cbWd*q-&W8!G+JiIx6N=|3lW3uz`~&2PUFwz|zf36QTe zwWK{%2+UeOwi~J#$WOOlE1vKP^k^~;$eH?Ctv1_0sc(osv;4q%(O~LUQ&vE3p7+7; zJ|EPts1?m8%VHFi=kde(uh*w+wx==yl<$WBn3uTUXpth)A-Z9sD@cL8tJmW>iv7H?YrBpYrhT*T>O5X`h3`>_UA-Wtp~$nWC|0w%%`BZ=56EuS_QJMr#&F9~NSa2^-c^(}AY4AOzWU&k2#;ykh>&Ctan2kj z%P12PGVBGhaG>|hbfm2;N6$40-WiHnr#(6Zg7|v>y~Vz7Gd%pP?X_j&RP(IH?0WTP zVcUN3_^-z;KYAY|+&X$afidx*?*_$1quf;ptzAJp+)#KT5MF}6e~5jHOKzuqynHZt_cTnPMbV) zq_6i`L10S5>r1gTni(SI@`Cu8)cN&kg>O#@U@5|Y7eoJFAbAicVpw6$!*sHr`oPro zlpEd{y*a%AVZq;i64Rfnes|`>{<{kme9hbD(+|=!o$FrkdWnqa-}h8L$?o5B8)AZe zDb0zq-jcFCZdm6lEunG?ACjR&bfSGMbBYV=>7(ePWXO~CNz7(It*94)=6nB<;Bb!A z!eL96uqp7AO|f2*iRYjtY-t2crR!f_$gFJ!a=}5x1X#3K-;+K9OQ~m^wR&^f$1zEu zQ17qPZHSxGy7*XzfsvrDrM?i2&@EXs8^9P@Ezx1$@4b~MUQ^g9$B`8W3WeG2>gF8{$XxfCv2T?_h|J%Lw{y#R!c8Klq!?r&s2z01L zo$h?(a6YUIO@S!UTqB2?tAQwLiD5xif4;<%l>WP_P&^w zBq=SEJj^npplDzQkTOw=X;+c-R~oXaNK?1IfDq!V_!{sc*Q-u5(y11DW*F||bC<00 z%W}Is+IipYXs#))s{Wb%K|&9P?bIrjSf+1#%@Odd^=ujj@ai2I7rHPQ0O2REC-@=3 zNG`tQB~w1JTB_%1A_D%nr~+q5jx1-IX%76!$a(OL6BRdPPQ*`d9)7 zGGsasSwIkZ)ia(S;|K?n^j%>4 zngbg)zE5SAS5Q}^PZF|mtiG!R8bf)KY+PuX^VpQ)ZSLw(&pRaHG(sIojt}>xBAyMh zg}d==h&YirFyG^pw>G$Z6*nbV-1qNmPHqxS2(EYP2Je005&N_riYMGQok4Z;$hyqhCW8PBXA%=La(?@(f15y#Uv^fjr| z+Tu{WL4_N$dK5A&pqDq|uF~N0kb(x(4a)g)JbcKiZ5ir&qY<$LkH{pV_ar0Kp@m&2#~;gtF5Q{Y?ujry$GAfs*re)v9Ply_*M9d(r5EthDBZcSN2Zez22A0c z5#<}#RtM8%I*Z&ACj(H+$~V`ig@;-PVkh9X_+sk-J~%n}6hUpNy&hNJI-eTw0`h%T zipTvlN+~U4%BUec2gAV?WZ4N>N`Q8fwr_Y}zmeP**-d36@wc$k zzU?*JbV!`T$AZrAm&GE2`TVC684XM(^LnC>5hu;4Vu<5dENX%d?`a<<)Wr@AMTgq^ z8Vj#j3>o2Ru3c!}(`6+kp*0tshQ{|Gm8mbi9B%3GS<+U`&CH48W$tWX@h17cfE36@ z2(wd81E@Uq(Z6>JG@r1q^<263eW+tz4W_Ux+*xdL&4M{U8k%@_*avAX{4e4n$q(RE7VSA48 zOGB)E%TFF(pFuW$f+nAhNk)=LeQ^p}GUNN#{iLQFq&E#>ezfRJn0TZI7wtThajc%9 zTetgxdW#T->xNCXqEq*?#TK`QZI91(v6sd3isjeggfG^?$9LPCa<<>tTRYIws7UoR z;O+=jGm%EhzQn~XH93J9KwIRku>ea1gN7|RTZj8Dn2yvy;&VoBWa1;IU(^a$WnzW% z0N`9m1tYwtjmC6x7({XG*tFJ=r)iSXR5jS*YP}Vgk+g|Z5)STTiYB@stp==eSjx0; zQoD5Kt;(J_0#9efGOi%Q;EK@XlnHmHbYOE?(vfwir4&rtS=2E6ty?R>2r1W=UTprK zZsg{4OmQsoR*h#kAoUODTq9@KUe!~Cp@J0|5kxyzB8?LazlgPIBS;Udsz?*_&z1zh z<{7HC5Cx0Y_%KK3F~avUEo!0s1NeOp9N&QaB4il45kyEZ+CAYb<(DQi!69geB=| z)o44XLJO(eyUvU;^P~ID&)%ZwR`bQOp7~NnhD@m>STaFM%A%Iyv~rj~Da&T9-dN3V zVS_C#@>6?q1=&=DQ73q86Txv3$I~7KBvNHoN$o6S{)H8by(fl*GD~A~r_Sq%fO~9F zHh#Jd_CA;B>McK^@75xmBmzBegha`u5QSV6I%)bKgi|%Wq-2#6rk;c(MV$G_{n8>X zuGT6J`&7ozkOAc(j=+vQoptN+igpBL1c^d>zz2#`z|^7G;rUDOXwf8@9(`foN+FB5 zvb4Ym1FWzC8*2p!!~hX+;^9!4lX#gLI;->bR7qDz&bGDv@!hsKR?>~XjjZCcJ|#)6 zeNhRt4oNKi2^v2>ZkvMU6X#d;_1^y8`!NSu+&y3V`*#>CJe(CfdP6_Kwtj5q8R7fS z;Xd_S;Z+((&&GCxJBJ)hU$SAApg6cbOJ6@nK!F@fcU(`o�)kPCZ_pp_v{TuSyW& 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

J{m`Ym#< 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�ZO*)u+I?}y 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

`o*T1wS+ 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

UBcKLy;)Vhle5X-cz`Gzdq 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 literal 0 HcmV?d00001 diff --git a/npm 2/kubernetes-mcp-server-windows-amd64/package.json b/npm 2/kubernetes-mcp-server-windows-amd64/package.json new file mode 100644 index 00000000..04b5d8ef --- /dev/null +++ b/npm 2/kubernetes-mcp-server-windows-amd64/package.json @@ -0,0 +1,11 @@ +{ + "name": "kubernetes-mcp-server-windows-amd64", + "version": "0.0.0", + "description": "Model Context Protocol (MCP) server for Kubernetes and OpenShift", + "os": [ + "win32" + ], + "cpu": [ + "x64" + ] +} diff --git a/npm 2/kubernetes-mcp-server-windows-arm64/package.json b/npm 2/kubernetes-mcp-server-windows-arm64/package.json new file mode 100644 index 00000000..38aa06f7 --- /dev/null +++ b/npm 2/kubernetes-mcp-server-windows-arm64/package.json @@ -0,0 +1,11 @@ +{ + "name": "kubernetes-mcp-server-windows-arm64", + "version": "0.0.0", + "description": "Model Context Protocol (MCP) server for Kubernetes and OpenShift", + "os": [ + "win32" + ], + "cpu": [ + "arm64" + ] +} diff --git a/pkg 2/config/config.go b/pkg 2/config/config.go new file mode 100644 index 00000000..970d8753 --- /dev/null +++ b/pkg 2/config/config.go @@ -0,0 +1,51 @@ +package config + +import ( + "os" + + "github.com/BurntSushi/toml" +) + +// StaticConfig is the configuration for the server. +// It allows to configure server specific settings and tools to be enabled or disabled. +type StaticConfig struct { + DeniedResources []GroupVersionKind `toml:"denied_resources"` + + LogLevel int `toml:"log_level,omitempty"` + Port string `toml:"port,omitempty"` + SSEBaseURL string `toml:"sse_base_url,omitempty"` + KubeConfig string `toml:"kubeconfig,omitempty"` + ListOutput string `toml:"list_output,omitempty"` + // When true, expose only tools annotated with readOnlyHint=true + ReadOnly bool `toml:"read_only,omitempty"` + // When true, disable tools annotated with destructiveHint=true + DisableDestructive bool `toml:"disable_destructive,omitempty"` + EnabledTools []string `toml:"enabled_tools,omitempty"` + DisabledTools []string `toml:"disabled_tools,omitempty"` + RequireOAuth bool `toml:"require_oauth,omitempty"` + AuthorizationURL string `toml:"authorization_url,omitempty"` + JwksURL string `toml:"jwks_url,omitempty"` + CertificateAuthority string `toml:"certificate_authority,omitempty"` + ServerURL string `toml:"server_url,omitempty"` +} + +type GroupVersionKind struct { + Group string `toml:"group"` + Version string `toml:"version"` + Kind string `toml:"kind,omitempty"` +} + +// ReadConfig reads the toml file and returns the StaticConfig. +func ReadConfig(configPath string) (*StaticConfig, error) { + configData, err := os.ReadFile(configPath) + if err != nil { + return nil, err + } + + var config *StaticConfig + err = toml.Unmarshal(configData, &config) + if err != nil { + return nil, err + } + return config, nil +} diff --git a/pkg 2/config/config_test.go b/pkg 2/config/config_test.go new file mode 100644 index 00000000..1f52361d --- /dev/null +++ b/pkg 2/config/config_test.go @@ -0,0 +1,156 @@ +package config + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestReadConfigMissingFile(t *testing.T) { + config, err := ReadConfig("non-existent-config.toml") + t.Run("returns error for missing file", func(t *testing.T) { + if err == nil { + t.Fatal("Expected error for missing file, got nil") + } + if config != nil { + t.Fatalf("Expected nil config for missing file, got %v", config) + } + }) +} + +func TestReadConfigInvalid(t *testing.T) { + invalidConfigPath := writeConfig(t, ` +[[denied_resources]] +group = "apps" +version = "v1" +kind = "Deployment" +[[denied_resources]] +group = "rbac.authorization.k8s.io" +version = "v1" +kind = "Role +`) + + config, err := ReadConfig(invalidConfigPath) + t.Run("returns error for invalid file", func(t *testing.T) { + if err == nil { + t.Fatal("Expected error for invalid file, got nil") + } + if config != nil { + t.Fatalf("Expected nil config for invalid file, got %v", config) + } + }) + t.Run("error message contains toml error with line number", func(t *testing.T) { + expectedError := "toml: line 9" + if err != nil && !strings.HasPrefix(err.Error(), expectedError) { + t.Fatalf("Expected error message '%s' to contain line number, got %v", expectedError, err) + } + }) +} + +func TestReadConfigValid(t *testing.T) { + validConfigPath := writeConfig(t, ` +log_level = 1 +port = "9999" +sse_base_url = "https://example.com" +kubeconfig = "./path/to/config" +list_output = "yaml" +read_only = true +disable_destructive = true + +denied_resources = [ + {group = "apps", version = "v1", kind = "Deployment"}, + {group = "rbac.authorization.k8s.io", version = "v1", kind = "Role"} +] + +enabled_tools = ["configuration_view", "events_list", "namespaces_list", "pods_list", "resources_list", "resources_get", "resources_create_or_update", "resources_delete"] +disabled_tools = ["pods_delete", "pods_top", "pods_log", "pods_run", "pods_exec"] +`) + + config, err := ReadConfig(validConfigPath) + t.Run("reads and unmarshalls file", func(t *testing.T) { + if err != nil { + t.Fatalf("ReadConfig returned an error for a valid file: %v", err) + } + if config == nil { + t.Fatal("ReadConfig returned a nil config for a valid file") + } + }) + t.Run("denied resources are parsed correctly", func(t *testing.T) { + if len(config.DeniedResources) != 2 { + t.Fatalf("Expected 2 denied resources, got %d", len(config.DeniedResources)) + } + if config.DeniedResources[0].Group != "apps" || + config.DeniedResources[0].Version != "v1" || + config.DeniedResources[0].Kind != "Deployment" { + t.Errorf("Unexpected denied resources: %v", config.DeniedResources[0]) + } + }) + t.Run("log_level parsed correctly", func(t *testing.T) { + if config.LogLevel != 1 { + t.Fatalf("Unexpected log level: %v", config.LogLevel) + } + }) + t.Run("port parsed correctly", func(t *testing.T) { + if config.Port != "9999" { + t.Fatalf("Unexpected port value: %v", config.Port) + } + }) + t.Run("sse_base_url parsed correctly", func(t *testing.T) { + if config.SSEBaseURL != "https://example.com" { + t.Fatalf("Unexpected sse_base_url value: %v", config.SSEBaseURL) + } + }) + t.Run("kubeconfig parsed correctly", func(t *testing.T) { + if config.KubeConfig != "./path/to/config" { + t.Fatalf("Unexpected kubeconfig value: %v", config.KubeConfig) + } + }) + t.Run("list_output parsed correctly", func(t *testing.T) { + if config.ListOutput != "yaml" { + t.Fatalf("Unexpected list_output value: %v", config.ListOutput) + } + }) + t.Run("read_only parsed correctly", func(t *testing.T) { + if !config.ReadOnly { + t.Fatalf("Unexpected read-only mode: %v", config.ReadOnly) + } + }) + t.Run("disable_destructive parsed correctly", func(t *testing.T) { + if !config.DisableDestructive { + t.Fatalf("Unexpected disable destructive: %v", config.DisableDestructive) + } + }) + t.Run("enabled_tools parsed correctly", func(t *testing.T) { + if len(config.EnabledTools) != 8 { + t.Fatalf("Unexpected enabled tools: %v", config.EnabledTools) + + } + for i, tool := range []string{"configuration_view", "events_list", "namespaces_list", "pods_list", "resources_list", "resources_get", "resources_create_or_update", "resources_delete"} { + if config.EnabledTools[i] != tool { + t.Errorf("Expected enabled tool %d to be %s, got %s", i, tool, config.EnabledTools[i]) + } + } + }) + t.Run("disabled_tools parsed correctly", func(t *testing.T) { + if len(config.DisabledTools) != 5 { + t.Fatalf("Unexpected disabled tools: %v", config.DisabledTools) + } + for i, tool := range []string{"pods_delete", "pods_top", "pods_log", "pods_run", "pods_exec"} { + if config.DisabledTools[i] != tool { + t.Errorf("Expected disabled tool %d to be %s, got %s", i, tool, config.DisabledTools[i]) + } + } + }) +} + +func writeConfig(t *testing.T, content string) string { + t.Helper() + tempDir := t.TempDir() + path := filepath.Join(tempDir, "config.toml") + err := os.WriteFile(path, []byte(content), 0644) + if err != nil { + t.Fatalf("Failed to write config file %s: %v", path, err) + } + return path +} diff --git a/pkg 2/helm/helm.go b/pkg 2/helm/helm.go new file mode 100644 index 00000000..186b50df --- /dev/null +++ b/pkg 2/helm/helm.go @@ -0,0 +1,142 @@ +package helm + +import ( + "context" + "fmt" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/registry" + "helm.sh/helm/v3/pkg/release" + "k8s.io/cli-runtime/pkg/genericclioptions" + "log" + "sigs.k8s.io/yaml" + "time" +) + +type Kubernetes interface { + genericclioptions.RESTClientGetter + NamespaceOrDefault(namespace string) string +} + +type Helm struct { + kubernetes Kubernetes +} + +// NewHelm creates a new Helm instance +func NewHelm(kubernetes Kubernetes) *Helm { + return &Helm{kubernetes: kubernetes} +} + +func (h *Helm) Install(ctx context.Context, chart string, values map[string]interface{}, name string, namespace string) (string, error) { + cfg, err := h.newAction(h.kubernetes.NamespaceOrDefault(namespace), false) + if err != nil { + return "", err + } + install := action.NewInstall(cfg) + if name == "" { + install.GenerateName = true + install.ReleaseName, _, _ = install.NameAndChart([]string{chart}) + } else { + install.ReleaseName = name + } + install.Namespace = h.kubernetes.NamespaceOrDefault(namespace) + install.Wait = true + install.Timeout = 5 * time.Minute + install.DryRun = false + + chartRequested, err := install.LocateChart(chart, cli.New()) + if err != nil { + return "", err + } + chartLoaded, err := loader.Load(chartRequested) + if err != nil { + return "", err + } + + installedRelease, err := install.RunWithContext(ctx, chartLoaded, values) + if err != nil { + return "", err + } + ret, err := yaml.Marshal(simplify(installedRelease)) + if err != nil { + return "", err + } + return string(ret), nil +} + +// List lists all the releases for the specified namespace (or current namespace if). Or allNamespaces is true, it lists all releases across all namespaces. +func (h *Helm) List(namespace string, allNamespaces bool) (string, error) { + cfg, err := h.newAction(namespace, allNamespaces) + if err != nil { + return "", err + } + list := action.NewList(cfg) + list.AllNamespaces = allNamespaces + releases, err := list.Run() + if err != nil { + return "", err + } else if len(releases) == 0 { + return "No Helm releases found", nil + } + ret, err := yaml.Marshal(simplify(releases...)) + if err != nil { + return "", err + } + return string(ret), nil +} + +func (h *Helm) Uninstall(name string, namespace string) (string, error) { + cfg, err := h.newAction(h.kubernetes.NamespaceOrDefault(namespace), false) + if err != nil { + return "", err + } + uninstall := action.NewUninstall(cfg) + uninstall.IgnoreNotFound = true + uninstall.Wait = true + uninstall.Timeout = 5 * time.Minute + uninstalledRelease, err := uninstall.Run(name) + if uninstalledRelease == nil && err == nil { + return fmt.Sprintf("Release %s not found", name), nil + } else if err != nil { + return "", err + } + return fmt.Sprintf("Uninstalled release %s %s", uninstalledRelease.Release.Name, uninstalledRelease.Info), nil +} + +func (h *Helm) newAction(namespace string, allNamespaces bool) (*action.Configuration, error) { + cfg := new(action.Configuration) + applicableNamespace := "" + if !allNamespaces { + applicableNamespace = h.kubernetes.NamespaceOrDefault(namespace) + } + registryClient, err := registry.NewClient() + if err != nil { + return nil, err + } + cfg.RegistryClient = registryClient + return cfg, cfg.Init(h.kubernetes, applicableNamespace, "", log.Printf) +} + +func simplify(release ...*release.Release) []map[string]interface{} { + ret := make([]map[string]interface{}, len(release)) + for i, r := range release { + ret[i] = map[string]interface{}{ + "name": r.Name, + "namespace": r.Namespace, + "revision": r.Version, + } + if r.Chart != nil { + ret[i]["chart"] = r.Chart.Metadata.Name + ret[i]["chartVersion"] = r.Chart.Metadata.Version + ret[i]["appVersion"] = r.Chart.Metadata.AppVersion + } + if r.Info != nil { + ret[i]["status"] = r.Info.Status.String() + if !r.Info.LastDeployed.IsZero() { + ret[i]["lastDeployed"] = r.Info.LastDeployed.Format(time.RFC1123Z) + } + } + } + return ret +} diff --git a/pkg 2/http/authorization.go b/pkg 2/http/authorization.go new file mode 100644 index 00000000..2b3152b8 --- /dev/null +++ b/pkg 2/http/authorization.go @@ -0,0 +1,179 @@ +package http + +import ( + "context" + "fmt" + "net/http" + "strings" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" + "k8s.io/klog/v2" + + "github.com/containers/kubernetes-mcp-server/pkg/mcp" +) + +const ( + Audience = "kubernetes-mcp-server" +) + +// AuthorizationMiddleware validates the OAuth flow using Kubernetes TokenReview API +func AuthorizationMiddleware(requireOAuth bool, serverURL string, oidcProvider *oidc.Provider, mcpServer *mcp.Server) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == healthEndpoint || r.URL.Path == oauthProtectedResourceEndpoint { + next.ServeHTTP(w, r) + return + } + if !requireOAuth { + next.ServeHTTP(w, r) + return + } + + audience := Audience + if serverURL != "" { + audience = serverURL + } + + authHeader := r.Header.Get("Authorization") + if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") { + klog.V(1).Infof("Authentication failed - missing or invalid bearer token: %s %s from %s", r.Method, r.URL.Path, r.RemoteAddr) + + if serverURL == "" { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s", error="missing_token"`, audience)) + } else { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s"", resource_metadata="%s%s", error="missing_token"`, audience, serverURL, oauthProtectedResourceEndpoint)) + } + http.Error(w, "Unauthorized: Bearer token required", http.StatusUnauthorized) + return + } + + token := strings.TrimPrefix(authHeader, "Bearer ") + + // Validate the token offline for simple sanity check + // Because missing expected audience and expired tokens must be + // rejected already. + claims, err := ParseJWTClaims(token) + if err == nil && claims != nil { + err = claims.Validate(audience) + } + if err != nil { + klog.V(1).Infof("Authentication failed - JWT validation error: %s %s from %s, error: %v", r.Method, r.URL.Path, r.RemoteAddr, err) + + if serverURL == "" { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s", error="invalid_token"`, audience)) + } else { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s"", resource_metadata="%s%s", error="invalid_token"`, audience, serverURL, oauthProtectedResourceEndpoint)) + } + http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized) + return + } + + if oidcProvider != nil { + // If OIDC Provider is configured, this token must be validated against it. + if err := validateTokenWithOIDC(r.Context(), oidcProvider, token, audience); err != nil { + klog.V(1).Infof("Authentication failed - OIDC token validation error: %s %s from %s, error: %v", r.Method, r.URL.Path, r.RemoteAddr, err) + + if serverURL == "" { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s", error="invalid_token"`, audience)) + } else { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s"", resource_metadata="%s%s", error="invalid_token"`, audience, serverURL, oauthProtectedResourceEndpoint)) + } + http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized) + return + } + } + + // Scopes are likely to be used for authorization. + scopes := claims.GetScopes() + klog.V(2).Infof("JWT token validated - Scopes: %v", scopes) + r = r.WithContext(context.WithValue(r.Context(), mcp.TokenScopesContextKey, scopes)) + + // Now, there are a couple of options: + // 1. If there is no authorization url configured for this MCP Server, + // that means this token will be used against the Kubernetes API Server. + // So that we need to validate the token using Kubernetes TokenReview API beforehand. + // 2. If there is an authorization url configured for this MCP Server, + // that means up to this point, the token is validated against the OIDC Provider already. + // 2. a. If this is the only token in the headers, this validated token + // is supposed to be used against the Kubernetes API Server as well. Therefore, + // TokenReview request must succeed. + // 2. b. If this is not the only token in the headers, the token in here is used + // only for authentication and authorization. Therefore, we need to send TokenReview request + // with the other token in the headers (TODO: still need to validate aud and exp of this token separately). + _, _, err = mcpServer.VerifyTokenAPIServer(r.Context(), token, audience) + if err != nil { + klog.V(1).Infof("Authentication failed - API Server token validation error: %s %s from %s, error: %v", r.Method, r.URL.Path, r.RemoteAddr, err) + + if serverURL == "" { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s", error="invalid_token"`, audience)) + } else { + w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Bearer realm="Kubernetes MCP Server", audience="%s"", resource_metadata="%s%s", error="invalid_token"`, audience, serverURL, oauthProtectedResourceEndpoint)) + } + http.Error(w, "Unauthorized: Invalid token", http.StatusUnauthorized) + return + } + + next.ServeHTTP(w, r) + }) + } +} + +var allSignatureAlgorithms = []jose.SignatureAlgorithm{ + jose.EdDSA, + jose.HS256, + jose.HS384, + jose.HS512, + jose.RS256, + jose.RS384, + jose.RS512, + jose.ES256, + jose.ES384, + jose.ES512, + jose.PS256, + jose.PS384, + jose.PS512, +} + +type JWTClaims struct { + jwt.Claims + Scope string `json:"scope,omitempty"` +} + +func (c *JWTClaims) GetScopes() []string { + if c.Scope == "" { + return nil + } + return strings.Fields(c.Scope) +} + +// Validate Checks if the JWT claims are valid and if the audience matches the expected one. +func (c *JWTClaims) Validate(audience string) error { + return c.Claims.Validate(jwt.Expected{ + AnyAudience: jwt.Audience{audience}, + }) +} + +func ParseJWTClaims(token string) (*JWTClaims, error) { + tkn, err := jwt.ParseSigned(token, allSignatureAlgorithms) + if err != nil { + return nil, fmt.Errorf("failed to parse JWT token: %w", err) + } + claims := &JWTClaims{} + err = tkn.UnsafeClaimsWithoutVerification(claims) + return claims, err +} + +func validateTokenWithOIDC(ctx context.Context, provider *oidc.Provider, token, audience string) error { + verifier := provider.Verifier(&oidc.Config{ + ClientID: audience, + }) + + _, err := verifier.Verify(ctx, token) + if err != nil { + return fmt.Errorf("JWT token verification failed: %v", err) + } + + return nil +} diff --git a/pkg 2/http/authorization_test.go b/pkg 2/http/authorization_test.go new file mode 100644 index 00000000..31ad8041 --- /dev/null +++ b/pkg 2/http/authorization_test.go @@ -0,0 +1,220 @@ +package http + +import ( + "strings" + "testing" + + "github.com/go-jose/go-jose/v4/jwt" +) + +const ( + // https://jwt.io/#token=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoyNTM0MDIyOTcxOTksImlhdCI6MCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJqdGkiOiI5OTIyMmQ1Ni0zNDBlLTRlYjYtODU4OC0yNjE0MTFmMzVkMjYiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImRlZmF1bHQiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImVhY2I2YWQyLTgwYjctNDE3OS04NDNkLTkyZWIxZTZiYmJhNiJ9fSwibmJmIjowLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0In0.0363P6xGmWpU-O9TAVkcOd95lPXxhI-_k5NKbHGNQeL--B8XMAz2vC8hpKnyC6rKOGifRTSR2XNHx_5fjd7lEA // notsecret + tokenBasicNotExpired = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoyNTM0MDIyOTcxOTksImlhdCI6MCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJqdGkiOiI5OTIyMmQ1Ni0zNDBlLTRlYjYtODU4OC0yNjE0MTFmMzVkMjYiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImRlZmF1bHQiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImVhY2I2YWQyLTgwYjctNDE3OS04NDNkLTkyZWIxZTZiYmJhNiJ9fSwibmJmIjowLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0In0.0363P6xGmWpU-O9TAVkcOd95lPXxhI-_k5NKbHGNQeL--B8XMAz2vC8hpKnyC6rKOGifRTSR2XNHx_5fjd7lEA" // notsecret + // https://jwt.io/#token=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoxLCJpYXQiOjAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiOTkyMjJkNTYtMzQwZS00ZWI2LTg1ODgtMjYxNDExZjM1ZDI2Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiJlYWNiNmFkMi04MGI3LTQxNzktODQzZC05MmViMWU2YmJiYTYifX0sIm5iZiI6MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.USsuGLsB_7MwG9i0__cFkVVZa0djtmQpc8Vwi56GrapAgVAcyTfmae3s83XMDP5AwcFnxhYxLCfiZWRJri6GTA // notsecret + tokenBasicExpired = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoxLCJpYXQiOjAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiOTkyMjJkNTYtMzQwZS00ZWI2LTg1ODgtMjYxNDExZjM1ZDI2Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiJlYWNiNmFkMi04MGI3LTQxNzktODQzZC05MmViMWU2YmJiYTYifX0sIm5iZiI6MCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.USsuGLsB_7MwG9i0__cFkVVZa0djtmQpc8Vwi56GrapAgVAcyTfmae3s83XMDP5AwcFnxhYxLCfiZWRJri6GTA" // notsecret + // https://jwt.io/#token=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoyNTM0MDIyOTcxOTksImlhdCI6MCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJqdGkiOiI5OTIyMmQ1Ni0zNDBlLTRlYjYtODU4OC0yNjE0MTFmMzVkMjYiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImRlZmF1bHQiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImVhY2I2YWQyLTgwYjctNDE3OS04NDNkLTkyZWIxZTZiYmJhNiJ9fSwibmJmIjowLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0Iiwic2NvcGUiOiJyZWFkIHdyaXRlIn0.vl5se9BuxoVDhvR7M5wGfkLoyMSYUiORMZVxl0CQ7jw3x53mZfGEkU_kkIVIl9Ui371qCCVVxdvuZPcAgbM6pQ // notsecret + tokenMultipleAudienceNotExpired = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijk4ZDU3YmUwNWI3ZjUzNWIwMzYyYjg2MDJhNTJlNGYxIn0.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrdWJlcm5ldGVzLW1jcC1zZXJ2ZXIiXSwiZXhwIjoyNTM0MDIyOTcxOTksImlhdCI6MCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJqdGkiOiI5OTIyMmQ1Ni0zNDBlLTRlYjYtODU4OC0yNjE0MTFmMzVkMjYiLCJrdWJlcm5ldGVzLmlvIjp7Im5hbWVzcGFjZSI6ImRlZmF1bHQiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6ImVhY2I2YWQyLTgwYjctNDE3OS04NDNkLTkyZWIxZTZiYmJhNiJ9fSwibmJmIjowLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0Iiwic2NvcGUiOiJyZWFkIHdyaXRlIn0.vl5se9BuxoVDhvR7M5wGfkLoyMSYUiORMZVxl0CQ7jw3x53mZfGEkU_kkIVIl9Ui371qCCVVxdvuZPcAgbM6pQ" // notsecret +) + +func TestParseJWTClaimsPayloadValid(t *testing.T) { + basicClaims, err := ParseJWTClaims(tokenBasicNotExpired) + t.Run("Is parseable", func(t *testing.T) { + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if basicClaims == nil { + t.Fatal("expected claims, got nil") + } + }) + t.Run("Parses issuer", func(t *testing.T) { + if basicClaims.Issuer != "https://kubernetes.default.svc.cluster.local" { + t.Errorf("expected issuer 'https://kubernetes.default.svc.cluster.local', got %s", basicClaims.Issuer) + } + }) + t.Run("Parses audience", func(t *testing.T) { + expectedAudiences := []string{"https://kubernetes.default.svc.cluster.local", "kubernetes-mcp-server"} + for _, expected := range expectedAudiences { + if !basicClaims.Audience.Contains(expected) { + t.Errorf("expected audience to contain %s", expected) + } + } + }) + t.Run("Parses expiration", func(t *testing.T) { + if *basicClaims.Expiry != jwt.NumericDate(253402297199) { + t.Errorf("expected expiration 253402297199, got %d", basicClaims.Expiry) + } + }) + t.Run("Parses scope", func(t *testing.T) { + scopeClaims, err := ParseJWTClaims(tokenMultipleAudienceNotExpired) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if scopeClaims == nil { + t.Fatal("expected claims, got nil") + } + + scopes := scopeClaims.GetScopes() + + expectedScopes := []string{"read", "write"} + if len(scopes) != len(expectedScopes) { + t.Errorf("expected %d scopes, got %d", len(expectedScopes), len(scopes)) + } + for i, expectedScope := range expectedScopes { + if scopes[i] != expectedScope { + t.Errorf("expected scope[%d] to be '%s', got '%s'", i, expectedScope, scopes[i]) + } + } + }) + t.Run("Parses expired token", func(t *testing.T) { + expiredClaims, err := ParseJWTClaims(tokenBasicExpired) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + + if *expiredClaims.Expiry != jwt.NumericDate(1) { + t.Errorf("expected expiration 1, got %d", basicClaims.Expiry) + } + }) +} + +func TestParseJWTClaimsPayloadInvalid(t *testing.T) { + t.Run("invalid token segments", func(t *testing.T) { + invalidToken := "header.payload.signature.extra" + + _, err := ParseJWTClaims(invalidToken) + if err == nil { + t.Fatal("expected error for invalid token segments, got nil") + } + + if !strings.Contains(err.Error(), "compact JWS format must have three parts") { + t.Errorf("expected invalid token segments error message, got %v", err) + } + }) + t.Run("invalid base64 payload", func(t *testing.T) { + invalidPayload := "invalid_base64" + tokenBasicNotExpired + + _, err := ParseJWTClaims(invalidPayload) + if err == nil { + t.Fatal("expected error for invalid base64, got nil") + } + + if !strings.Contains(err.Error(), "illegal base64 data") { + t.Errorf("expected decode error message, got %v", err) + } + }) +} + +func TestJWTTokenValidate(t *testing.T) { + t.Run("expired token returns error", func(t *testing.T) { + claims, err := ParseJWTClaims(tokenBasicExpired) + if err != nil { + t.Fatalf("expected no error for expired token parsing, got %v", err) + } + + err = claims.Validate("kubernetes-mcp-server") + if err == nil { + t.Fatalf("expected error for expired token, got nil") + } + + if !strings.Contains(err.Error(), "token is expired (exp)") { + t.Errorf("expected expiration error message, got %v", err) + } + }) + + t.Run("multiple audiences with correct one", func(t *testing.T) { + claims, err := ParseJWTClaims(tokenMultipleAudienceNotExpired) + if err != nil { + t.Fatalf("expected no error for multiple audience token parsing, got %v", err) + } + if claims == nil { + t.Fatalf("expected claims to be returned, got nil") + } + + err = claims.Validate("kubernetes-mcp-server") + if err != nil { + t.Fatalf("expected no error for valid audience, got %v", err) + } + }) + + t.Run("multiple audiences with mismatch returns error", func(t *testing.T) { + claims, err := ParseJWTClaims(tokenMultipleAudienceNotExpired) + if err != nil { + t.Fatalf("expected no error for multiple audience token parsing, got %v", err) + } + if claims == nil { + t.Fatalf("expected claims to be returned, got nil") + } + + err = claims.Validate("missing-audience") + if err == nil { + t.Fatalf("expected error for token with wrong audience, got nil") + } + + if !strings.Contains(err.Error(), "invalid audience claim (aud)") { + t.Errorf("expected audience mismatch error, got %v", err) + } + }) +} + +func TestJWTClaimsGetScopes(t *testing.T) { + t.Run("no scopes", func(t *testing.T) { + claims, err := ParseJWTClaims(tokenBasicExpired) + if err != nil { + t.Fatalf("expected no error for parsing token, got %v", err) + } + + if scopes := claims.GetScopes(); len(scopes) != 0 { + t.Errorf("expected no scopes, got %d", len(scopes)) + } + }) + t.Run("single scope", func(t *testing.T) { + claims := &JWTClaims{ + Scope: "read", + } + scopes := claims.GetScopes() + expected := []string{"read"} + + if len(scopes) != 1 { + t.Errorf("expected 1 scope, got %d", len(scopes)) + } + if scopes[0] != expected[0] { + t.Errorf("expected scope 'read', got '%s'", scopes[0]) + } + }) + + t.Run("multiple scopes", func(t *testing.T) { + claims := &JWTClaims{ + Scope: "read write admin", + } + scopes := claims.GetScopes() + expected := []string{"read", "write", "admin"} + + if len(scopes) != 3 { + t.Errorf("expected 3 scopes, got %d", len(scopes)) + } + + for i, expectedScope := range expected { + if i >= len(scopes) || scopes[i] != expectedScope { + t.Errorf("expected scope[%d] to be '%s', got '%s'", i, expectedScope, scopes[i]) + } + } + }) + + t.Run("scopes with extra whitespace", func(t *testing.T) { + claims := &JWTClaims{ + Scope: " read write admin ", + } + scopes := claims.GetScopes() + expected := []string{"read", "write", "admin"} + + if len(scopes) != 3 { + t.Errorf("expected 3 scopes, got %d", len(scopes)) + } + + for i, expectedScope := range expected { + if i >= len(scopes) || scopes[i] != expectedScope { + t.Errorf("expected scope[%d] to be '%s', got '%s'", i, expectedScope, scopes[i]) + } + } + }) +} diff --git a/pkg 2/http/http.go b/pkg 2/http/http.go new file mode 100644 index 00000000..602a4002 --- /dev/null +++ b/pkg 2/http/http.go @@ -0,0 +1,119 @@ +package http + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "github.com/coreos/go-oidc/v3/oidc" + + "k8s.io/klog/v2" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/mcp" +) + +const ( + oauthProtectedResourceEndpoint = "/.well-known/oauth-protected-resource" + healthEndpoint = "/healthz" + mcpEndpoint = "/mcp" + sseEndpoint = "/sse" + sseMessageEndpoint = "/message" +) + +func Serve(ctx context.Context, mcpServer *mcp.Server, staticConfig *config.StaticConfig, oidcProvider *oidc.Provider) error { + mux := http.NewServeMux() + + wrappedMux := RequestMiddleware( + AuthorizationMiddleware(staticConfig.RequireOAuth, staticConfig.ServerURL, oidcProvider, mcpServer)(mux), + ) + + httpServer := &http.Server{ + Addr: ":" + staticConfig.Port, + Handler: wrappedMux, + } + + sseServer := mcpServer.ServeSse(staticConfig.SSEBaseURL, httpServer) + streamableHttpServer := mcpServer.ServeHTTP(httpServer) + mux.Handle(sseEndpoint, sseServer) + mux.Handle(sseMessageEndpoint, sseServer) + mux.Handle(mcpEndpoint, streamableHttpServer) + mux.HandleFunc(healthEndpoint, func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + mux.HandleFunc(oauthProtectedResourceEndpoint, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + var authServers []string + if staticConfig.AuthorizationURL != "" { + authServers = []string{staticConfig.AuthorizationURL} + } else { + // Fallback to Kubernetes API server host if authorization_server is not configured + if apiServerHost := mcpServer.GetKubernetesAPIServerHost(); apiServerHost != "" { + authServers = []string{apiServerHost} + } + } + + response := map[string]interface{}{ + "authorization_servers": authServers, + "authorization_server": authServers[0], + "scopes_supported": mcpServer.GetEnabledTools(), + "bearer_methods_supported": []string{"header"}, + } + + if staticConfig.ServerURL != "" { + response["resource"] = staticConfig.ServerURL + } + + if staticConfig.JwksURL != "" { + response["jwks_uri"] = staticConfig.JwksURL + } + + w.WriteHeader(http.StatusOK) + if err := json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + }) + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + serverErr := make(chan error, 1) + go func() { + klog.V(0).Infof("Streaming and SSE HTTP servers starting on port %s and paths /mcp, /sse, /message", staticConfig.Port) + if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + serverErr <- err + } + }() + + select { + case sig := <-sigChan: + klog.V(0).Infof("Received signal %v, initiating graceful shutdown", sig) + cancel() + case <-ctx.Done(): + klog.V(0).Infof("Context cancelled, initiating graceful shutdown") + case err := <-serverErr: + klog.Errorf("HTTP server error: %v", err) + return err + } + + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second) + defer shutdownCancel() + + klog.V(0).Infof("Shutting down HTTP server gracefully...") + if err := httpServer.Shutdown(shutdownCtx); err != nil { + klog.Errorf("HTTP server shutdown error: %v", err) + return err + } + + klog.V(0).Infof("HTTP server shutdown complete") + return nil +} diff --git a/pkg 2/http/http_test.go b/pkg 2/http/http_test.go new file mode 100644 index 00000000..89e091fe --- /dev/null +++ b/pkg 2/http/http_test.go @@ -0,0 +1,515 @@ +package http + +import ( + "bufio" + "bytes" + "context" + "crypto/rand" + "crypto/rsa" + "flag" + "fmt" + "net" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "testing" + "time" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/coreos/go-oidc/v3/oidc/oidctest" + "golang.org/x/sync/errgroup" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/klog/v2" + "k8s.io/klog/v2/textlogger" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/mcp" +) + +type httpContext struct { + klogState klog.State + LogBuffer bytes.Buffer + HttpAddress string // HTTP server address + timeoutCancel context.CancelFunc // Release resources if test completes before the timeout + StopServer context.CancelFunc + WaitForShutdown func() error + StaticConfig *config.StaticConfig + OidcProvider *oidc.Provider +} + +func (c *httpContext) beforeEach(t *testing.T) { + t.Helper() + http.DefaultClient.Timeout = 10 * time.Second + if c.StaticConfig == nil { + c.StaticConfig = &config.StaticConfig{} + } + // Fake Kubernetes configuration + fakeConfig := api.NewConfig() + fakeConfig.Clusters["fake"] = api.NewCluster() + fakeConfig.Clusters["fake"].Server = "https://example.com" + fakeConfig.Contexts["fake-context"] = api.NewContext() + fakeConfig.Contexts["fake-context"].Cluster = "fake" + fakeConfig.CurrentContext = "fake-context" + kubeConfig := filepath.Join(t.TempDir(), "config") + _ = clientcmd.WriteToFile(*fakeConfig, kubeConfig) + _ = os.Setenv("KUBECONFIG", kubeConfig) + // Capture logging + c.klogState = klog.CaptureState() + flags := flag.NewFlagSet("test", flag.ContinueOnError) + klog.InitFlags(flags) + _ = flags.Set("v", "5") + klog.SetLogger(textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(5), textlogger.Output(&c.LogBuffer)))) + // Start server in random port + ln, err := net.Listen("tcp", "0.0.0.0:0") + if err != nil { + t.Fatalf("Failed to find random port for HTTP server: %v", err) + } + c.HttpAddress = ln.Addr().String() + if randomPortErr := ln.Close(); randomPortErr != nil { + t.Fatalf("Failed to close random port listener: %v", randomPortErr) + } + c.StaticConfig.Port = fmt.Sprintf("%d", ln.Addr().(*net.TCPAddr).Port) + mcpServer, err := mcp.NewServer(mcp.Configuration{ + Profile: mcp.Profiles[0], + StaticConfig: c.StaticConfig, + }) + if err != nil { + t.Fatalf("Failed to create MCP server: %v", err) + } + var timeoutCtx, cancelCtx context.Context + timeoutCtx, c.timeoutCancel = context.WithTimeout(t.Context(), 10*time.Second) + group, gc := errgroup.WithContext(timeoutCtx) + cancelCtx, c.StopServer = context.WithCancel(gc) + group.Go(func() error { return Serve(cancelCtx, mcpServer, c.StaticConfig, c.OidcProvider) }) + c.WaitForShutdown = group.Wait + // Wait for HTTP server to start (using net) + for i := 0; i < 10; i++ { + conn, err := net.Dial("tcp", c.HttpAddress) + if err == nil { + _ = conn.Close() + break + } + time.Sleep(50 * time.Millisecond) // Wait before retrying + } +} + +func (c *httpContext) afterEach(t *testing.T) { + t.Helper() + c.StopServer() + err := c.WaitForShutdown() + if err != nil { + t.Errorf("HTTP server did not shut down gracefully: %v", err) + } + c.timeoutCancel() + c.klogState.Restore() + _ = os.Setenv("KUBECONFIG", "") +} + +func testCase(t *testing.T, test func(c *httpContext)) { + testCaseWithContext(t, &httpContext{}, test) +} + +func testCaseWithContext(t *testing.T, httpCtx *httpContext, test func(c *httpContext)) { + httpCtx.beforeEach(t) + t.Cleanup(func() { httpCtx.afterEach(t) }) + test(httpCtx) +} + +func NewOidcTestServer(t *testing.T) (privateKey *rsa.PrivateKey, oidcProvider *oidc.Provider, httpServer *httptest.Server) { + t.Helper() + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("failed to generate private key for oidc: %v", err) + } + oidcServer := &oidctest.Server{ + PublicKeys: []oidctest.PublicKey{ + { + PublicKey: privateKey.Public(), + KeyID: "test-oidc-key-id", + Algorithm: oidc.RS256, + }, + }, + } + httpServer = httptest.NewServer(oidcServer) + oidcServer.SetIssuer(httpServer.URL) + oidcProvider, err = oidc.NewProvider(t.Context(), httpServer.URL) + if err != nil { + t.Fatalf("failed to create OIDC provider: %v", err) + } + return +} + +func TestGracefulShutdown(t *testing.T) { + testCase(t, func(ctx *httpContext) { + ctx.StopServer() + err := ctx.WaitForShutdown() + t.Run("Stops gracefully", func(t *testing.T) { + if err != nil { + t.Errorf("Expected graceful shutdown, but got error: %v", err) + } + }) + t.Run("Stops on context cancel", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Context cancelled, initiating graceful shutdown") { + t.Errorf("Context cancelled, initiating graceful shutdown, got: %s", ctx.LogBuffer.String()) + } + }) + t.Run("Starts server shutdown", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Shutting down HTTP server gracefully") { + t.Errorf("Expected graceful shutdown log, got: %s", ctx.LogBuffer.String()) + } + }) + t.Run("Server shutdown completes", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "HTTP server shutdown complete") { + t.Errorf("Expected HTTP server shutdown completed log, got: %s", ctx.LogBuffer.String()) + } + }) + }) +} + +func TestSseTransport(t *testing.T) { + testCase(t, func(ctx *httpContext) { + sseResp, sseErr := http.Get(fmt.Sprintf("http://%s/sse", ctx.HttpAddress)) + t.Cleanup(func() { _ = sseResp.Body.Close() }) + t.Run("Exposes SSE endpoint at /sse", func(t *testing.T) { + if sseErr != nil { + t.Fatalf("Failed to get SSE endpoint: %v", sseErr) + } + if sseResp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", sseResp.StatusCode) + } + }) + t.Run("SSE endpoint returns text/event-stream content type", func(t *testing.T) { + if sseResp.Header.Get("Content-Type") != "text/event-stream" { + t.Errorf("Expected Content-Type text/event-stream, got %s", sseResp.Header.Get("Content-Type")) + } + }) + responseReader := bufio.NewReader(sseResp.Body) + event, eventErr := responseReader.ReadString('\n') + endpoint, endpointErr := responseReader.ReadString('\n') + t.Run("SSE endpoint returns stream with messages endpoint", func(t *testing.T) { + if eventErr != nil { + t.Fatalf("Failed to read SSE response body (event): %v", eventErr) + } + if event != "event: endpoint\n" { + t.Errorf("Expected SSE event 'endpoint', got %s", event) + } + if endpointErr != nil { + t.Fatalf("Failed to read SSE response body (endpoint): %v", endpointErr) + } + if !strings.HasPrefix(endpoint, "data: /message?sessionId=") { + t.Errorf("Expected SSE data: '/message', got %s", endpoint) + } + }) + messageResp, messageErr := http.Post( + fmt.Sprintf("http://%s/message?sessionId=%s", ctx.HttpAddress, strings.TrimSpace(endpoint[25:])), + "application/json", + bytes.NewBufferString("{}"), + ) + t.Cleanup(func() { _ = messageResp.Body.Close() }) + t.Run("Exposes message endpoint at /message", func(t *testing.T) { + if messageErr != nil { + t.Fatalf("Failed to get message endpoint: %v", messageErr) + } + if messageResp.StatusCode != http.StatusAccepted { + t.Errorf("Expected HTTP 202 OK, got %d", messageResp.StatusCode) + } + }) + }) +} + +func TestStreamableHttpTransport(t *testing.T) { + testCase(t, func(ctx *httpContext) { + mcpGetResp, mcpGetErr := http.Get(fmt.Sprintf("http://%s/mcp", ctx.HttpAddress)) + t.Cleanup(func() { _ = mcpGetResp.Body.Close() }) + t.Run("Exposes MCP GET endpoint at /mcp", func(t *testing.T) { + if mcpGetErr != nil { + t.Fatalf("Failed to get MCP endpoint: %v", mcpGetErr) + } + if mcpGetResp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", mcpGetResp.StatusCode) + } + }) + t.Run("MCP GET endpoint returns text/event-stream content type", func(t *testing.T) { + if mcpGetResp.Header.Get("Content-Type") != "text/event-stream" { + t.Errorf("Expected Content-Type text/event-stream (GET), got %s", mcpGetResp.Header.Get("Content-Type")) + } + }) + mcpPostResp, mcpPostErr := http.Post(fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), "application/json", bytes.NewBufferString("{}")) + t.Cleanup(func() { _ = mcpPostResp.Body.Close() }) + t.Run("Exposes MCP POST endpoint at /mcp", func(t *testing.T) { + if mcpPostErr != nil { + t.Fatalf("Failed to post to MCP endpoint: %v", mcpPostErr) + } + if mcpPostResp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", mcpPostResp.StatusCode) + } + }) + t.Run("MCP POST endpoint returns application/json content type", func(t *testing.T) { + if mcpPostResp.Header.Get("Content-Type") != "application/json" { + t.Errorf("Expected Content-Type application/json (POST), got %s", mcpPostResp.Header.Get("Content-Type")) + } + }) + }) +} + +func TestHealthCheck(t *testing.T) { + testCase(t, func(ctx *httpContext) { + t.Run("Exposes health check endpoint at /healthz", func(t *testing.T) { + resp, err := http.Get(fmt.Sprintf("http://%s/healthz", ctx.HttpAddress)) + if err != nil { + t.Fatalf("Failed to get health check endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + if resp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", resp.StatusCode) + } + }) + }) + // Health exposed even when require Authorization + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}}, func(ctx *httpContext) { + resp, err := http.Get(fmt.Sprintf("http://%s/healthz", ctx.HttpAddress)) + if err != nil { + t.Fatalf("Failed to get health check endpoint with OAuth: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close() }) + t.Run("Health check with OAuth returns HTTP 200 OK", func(t *testing.T) { + if resp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", resp.StatusCode) + } + }) + }) +} + +func TestWellKnownOAuthProtectedResource(t *testing.T) { + testCase(t, func(ctx *httpContext) { + resp, err := http.Get(fmt.Sprintf("http://%s/.well-known/oauth-protected-resource", ctx.HttpAddress)) + t.Cleanup(func() { _ = resp.Body.Close() }) + t.Run("Exposes .well-known/oauth-protected-resource endpoint", func(t *testing.T) { + if err != nil { + t.Fatalf("Failed to get .well-known/oauth-protected-resource endpoint: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("Expected HTTP 200 OK, got %d", resp.StatusCode) + } + }) + t.Run(".well-known/oauth-protected-resource returns application/json content type", func(t *testing.T) { + if resp.Header.Get("Content-Type") != "application/json" { + t.Errorf("Expected Content-Type application/json, got %s", resp.Header.Get("Content-Type")) + } + }) + }) +} + +func TestMiddlewareLogging(t *testing.T) { + testCase(t, func(ctx *httpContext) { + _, _ = http.Get(fmt.Sprintf("http://%s/.well-known/oauth-protected-resource", ctx.HttpAddress)) + t.Run("Logs HTTP requests and responses", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "GET /.well-known/oauth-protected-resource 200") { + t.Errorf("Expected log entry for GET /.well-known/oauth-protected-resource, got: %s", ctx.LogBuffer.String()) + } + }) + t.Run("Logs HTTP request duration", func(t *testing.T) { + expected := `"GET /.well-known/oauth-protected-resource 200 (.+)"` + m := regexp.MustCompile(expected).FindStringSubmatch(ctx.LogBuffer.String()) + if len(m) != 2 { + t.Fatalf("Expected log entry to contain duration, got %s", ctx.LogBuffer.String()) + } + duration, err := time.ParseDuration(m[1]) + if err != nil { + t.Fatalf("Failed to parse duration from log entry: %v", err) + } + if duration < 0 { + t.Errorf("Expected duration to be non-negative, got %v", duration) + } + }) + }) +} + +func TestAuthorizationUnauthorized(t *testing.T) { + // Missing Authorization header + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}}, func(ctx *httpContext) { + resp, err := http.Get(fmt.Sprintf("http://%s/mcp", ctx.HttpAddress)) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with MISSING Authorization header returns 401 - Unauthorized", func(t *testing.T) { + if resp.StatusCode != 401 { + t.Errorf("Expected HTTP 401, got %d", resp.StatusCode) + } + }) + t.Run("Protected resource with MISSING Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="missing_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with MISSING Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - missing or invalid bearer token") { + t.Errorf("Expected log entry for missing or invalid bearer token, got: %s", ctx.LogBuffer.String()) + } + }) + }) + // Authorization header without Bearer prefix + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}}, func(ctx *httpContext) { + req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + req.Header.Set("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l") + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with INCOMPATIBLE Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="missing_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with INCOMPATIBLE Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - missing or invalid bearer token") { + t.Errorf("Expected log entry for missing or invalid bearer token, got: %s", ctx.LogBuffer.String()) + } + }) + }) + // Invalid Authorization header + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}}, func(ctx *httpContext) { + req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + req.Header.Set("Authorization", "Bearer invalid_base64"+tokenBasicNotExpired) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with INVALID Authorization header returns 401 - Unauthorized", func(t *testing.T) { + if resp.StatusCode != 401 { + t.Errorf("Expected HTTP 401, got %d", resp.StatusCode) + } + }) + t.Run("Protected resource with INVALID Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="invalid_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with INVALID Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - JWT validation error") && + !strings.Contains(ctx.LogBuffer.String(), "error: failed to parse JWT token: illegal base64 data") { + t.Errorf("Expected log entry for JWT validation error, got: %s", ctx.LogBuffer.String()) + } + }) + }) + // Expired Authorization Bearer token + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}}, func(ctx *httpContext) { + req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + req.Header.Set("Authorization", "Bearer "+tokenBasicExpired) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with EXPIRED Authorization header returns 401 - Unauthorized", func(t *testing.T) { + if resp.StatusCode != 401 { + t.Errorf("Expected HTTP 401, got %d", resp.StatusCode) + } + }) + t.Run("Protected resource with EXPIRED Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="invalid_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with EXPIRED Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - JWT validation error") && + !strings.Contains(ctx.LogBuffer.String(), "validation failed, token is expired (exp)") { + t.Errorf("Expected log entry for JWT validation error, got: %s", ctx.LogBuffer.String()) + } + }) + }) + // Failed OIDC validation + key, oidcProvider, httpServer := NewOidcTestServer(t) + t.Cleanup(httpServer.Close) + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}, OidcProvider: oidcProvider}, func(ctx *httpContext) { + req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + req.Header.Set("Authorization", "Bearer "+tokenBasicNotExpired) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with INVALID OIDC Authorization header returns 401 - Unauthorized", func(t *testing.T) { + if resp.StatusCode != 401 { + t.Errorf("Expected HTTP 401, got %d", resp.StatusCode) + } + }) + t.Run("Protected resource with INVALID OIDC Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="invalid_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with INVALID OIDC Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - OIDC token validation error") && + !strings.Contains(ctx.LogBuffer.String(), "JWT token verification failed: oidc: id token issued by a different provider") { + t.Errorf("Expected log entry for OIDC validation error, got: %s", ctx.LogBuffer.String()) + } + }) + }) + // Failed Kubernetes TokenReview + rawClaims := `{ + "iss": "` + httpServer.URL + `", + "exp": ` + strconv.FormatInt(time.Now().Add(time.Hour).Unix(), 10) + `, + "aud": "kubernetes-mcp-server" + }` + validOidcToken := oidctest.SignIDToken(key, "test-oidc-key-id", oidc.RS256, rawClaims) + testCaseWithContext(t, &httpContext{StaticConfig: &config.StaticConfig{RequireOAuth: true}, OidcProvider: oidcProvider}, func(ctx *httpContext) { + req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/mcp", ctx.HttpAddress), nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + req.Header.Set("Authorization", "Bearer "+validOidcToken) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to get protected endpoint: %v", err) + } + t.Cleanup(func() { _ = resp.Body.Close }) + t.Run("Protected resource with INVALID KUBERNETES Authorization header returns 401 - Unauthorized", func(t *testing.T) { + if resp.StatusCode != 401 { + t.Errorf("Expected HTTP 401, got %d", resp.StatusCode) + } + }) + t.Run("Protected resource with INVALID KUBERNETES Authorization header returns WWW-Authenticate header", func(t *testing.T) { + authHeader := resp.Header.Get("WWW-Authenticate") + expected := `Bearer realm="Kubernetes MCP Server", audience="kubernetes-mcp-server", error="invalid_token"` + if authHeader != expected { + t.Errorf("Expected WWW-Authenticate header to be %q, got %q", expected, authHeader) + } + }) + t.Run("Protected resource with INVALID KUBERNETES Authorization header logs error", func(t *testing.T) { + if !strings.Contains(ctx.LogBuffer.String(), "Authentication failed - API Server token validation error") { + t.Errorf("Expected log entry for Kubernetes TokenReview error, got: %s", ctx.LogBuffer.String()) + } + }) + }) +} diff --git a/pkg 2/http/middleware.go b/pkg 2/http/middleware.go new file mode 100644 index 00000000..0c4c4102 --- /dev/null +++ b/pkg 2/http/middleware.go @@ -0,0 +1,66 @@ +package http + +import ( + "bufio" + "net" + "net/http" + "time" + + "k8s.io/klog/v2" +) + +func RequestMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/healthz" { + next.ServeHTTP(w, r) + return + } + + start := time.Now() + + lrw := &loggingResponseWriter{ + ResponseWriter: w, + statusCode: http.StatusOK, + } + + next.ServeHTTP(lrw, r) + + duration := time.Since(start) + klog.V(5).Infof("%s %s %d %v", r.Method, r.URL.Path, lrw.statusCode, duration) + }) +} + +type loggingResponseWriter struct { + http.ResponseWriter + statusCode int + headerWritten bool +} + +func (lrw *loggingResponseWriter) WriteHeader(code int) { + if !lrw.headerWritten { + lrw.statusCode = code + lrw.headerWritten = true + lrw.ResponseWriter.WriteHeader(code) + } +} + +func (lrw *loggingResponseWriter) Write(b []byte) (int, error) { + if !lrw.headerWritten { + lrw.statusCode = http.StatusOK + lrw.headerWritten = true + } + return lrw.ResponseWriter.Write(b) +} + +func (lrw *loggingResponseWriter) Flush() { + if flusher, ok := lrw.ResponseWriter.(http.Flusher); ok { + flusher.Flush() + } +} + +func (lrw *loggingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if hijacker, ok := lrw.ResponseWriter.(http.Hijacker); ok { + return hijacker.Hijack() + } + return nil, nil, http.ErrNotSupported +} diff --git a/pkg 2/kubernetes/accesscontrol.go b/pkg 2/kubernetes/accesscontrol.go new file mode 100644 index 00000000..e35b5dfb --- /dev/null +++ b/pkg 2/kubernetes/accesscontrol.go @@ -0,0 +1,40 @@ +package kubernetes + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +// isAllowed checks the resource is in denied list or not. +// If it is in denied list, this function returns false. +func isAllowed( + staticConfig *config.StaticConfig, // TODO: maybe just use the denied resource slice + gvk *schema.GroupVersionKind, +) bool { + if staticConfig == nil { + return true + } + + for _, val := range staticConfig.DeniedResources { + // If kind is empty, that means Group/Version pair is denied entirely + if val.Kind == "" { + if gvk.Group == val.Group && gvk.Version == val.Version { + return false + } + } + if gvk.Group == val.Group && + gvk.Version == val.Version && + gvk.Kind == val.Kind { + return false + } + } + + return true +} + +func isNotAllowedError(gvk *schema.GroupVersionKind) error { + return fmt.Errorf("resource not allowed: %s", gvk.String()) +} diff --git a/pkg 2/kubernetes/accesscontrol_clientset.go b/pkg 2/kubernetes/accesscontrol_clientset.go new file mode 100644 index 00000000..ed875c64 --- /dev/null +++ b/pkg 2/kubernetes/accesscontrol_clientset.go @@ -0,0 +1,141 @@ +package kubernetes + +import ( + "context" + "fmt" + + authenticationv1api "k8s.io/api/authentication/v1" + authorizationv1api "k8s.io/api/authorization/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes" + authenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1" + authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/remotecommand" + "k8s.io/metrics/pkg/apis/metrics" + metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1" + metricsv1beta1 "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +// AccessControlClientset is a limited clientset delegating interface to the standard kubernetes.Clientset +// Only a limited set of functions are implemented with a single point of access to the kubernetes API where +// apiVersion and kinds are checked for allowed access +type AccessControlClientset struct { + cfg *rest.Config + delegate kubernetes.Interface + discoveryClient discovery.DiscoveryInterface + metricsV1beta1 *metricsv1beta1.MetricsV1beta1Client + staticConfig *config.StaticConfig // TODO: maybe just store the denied resource slice +} + +func (a *AccessControlClientset) DiscoveryClient() discovery.DiscoveryInterface { + return a.discoveryClient +} + +func (a *AccessControlClientset) Pods(namespace string) (corev1.PodInterface, error) { + gvk := &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + return a.delegate.CoreV1().Pods(namespace), nil +} + +func (a *AccessControlClientset) PodsExec(namespace, name string, podExecOptions *v1.PodExecOptions) (remotecommand.Executor, error) { + gvk := &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + // Compute URL + // https://github.com/kubernetes/kubectl/blob/5366de04e168bcbc11f5e340d131a9ca8b7d0df4/pkg/cmd/exec/exec.go#L382-L397 + execRequest := a.delegate.CoreV1().RESTClient(). + Post(). + Resource("pods"). + Namespace(namespace). + Name(name). + SubResource("exec") + execRequest.VersionedParams(podExecOptions, ParameterCodec) + spdyExec, err := remotecommand.NewSPDYExecutor(a.cfg, "POST", execRequest.URL()) + if err != nil { + return nil, err + } + webSocketExec, err := remotecommand.NewWebSocketExecutor(a.cfg, "GET", execRequest.URL().String()) + if err != nil { + return nil, err + } + return remotecommand.NewFallbackExecutor(webSocketExec, spdyExec, func(err error) bool { + return httpstream.IsUpgradeFailure(err) || httpstream.IsHTTPSProxyError(err) + }) +} + +func (a *AccessControlClientset) PodsMetricses(ctx context.Context, namespace, name string, listOptions metav1.ListOptions) (*metrics.PodMetricsList, error) { + gvk := &schema.GroupVersionKind{Group: metrics.GroupName, Version: metricsv1beta1api.SchemeGroupVersion.Version, Kind: "PodMetrics"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + versionedMetrics := &metricsv1beta1api.PodMetricsList{} + var err error + if name != "" { + m, err := a.metricsV1beta1.PodMetricses(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get metrics for pod %s/%s: %w", namespace, name, err) + } + versionedMetrics.Items = []metricsv1beta1api.PodMetrics{*m} + } else { + versionedMetrics, err = a.metricsV1beta1.PodMetricses(namespace).List(ctx, listOptions) + if err != nil { + return nil, fmt.Errorf("failed to list pod metrics in namespace %s: %w", namespace, err) + } + } + convertedMetrics := &metrics.PodMetricsList{} + return convertedMetrics, metricsv1beta1api.Convert_v1beta1_PodMetricsList_To_metrics_PodMetricsList(versionedMetrics, convertedMetrics, nil) +} + +func (a *AccessControlClientset) Services(namespace string) (corev1.ServiceInterface, error) { + gvk := &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + return a.delegate.CoreV1().Services(namespace), nil +} + +func (a *AccessControlClientset) SelfSubjectAccessReviews() (authorizationv1.SelfSubjectAccessReviewInterface, error) { + gvk := &schema.GroupVersionKind{Group: authorizationv1api.GroupName, Version: authorizationv1api.SchemeGroupVersion.Version, Kind: "SelfSubjectAccessReview"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + return a.delegate.AuthorizationV1().SelfSubjectAccessReviews(), nil +} + +// TokenReview returns TokenReviewInterface +func (a *AccessControlClientset) TokenReview() (authenticationv1.TokenReviewInterface, error) { + gvk := &schema.GroupVersionKind{Group: authenticationv1api.GroupName, Version: authorizationv1api.SchemeGroupVersion.Version, Kind: "TokenReview"} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + return a.delegate.AuthenticationV1().TokenReviews(), nil +} + +func NewAccessControlClientset(cfg *rest.Config, staticConfig *config.StaticConfig) (*AccessControlClientset, error) { + clientSet, err := kubernetes.NewForConfig(cfg) + if err != nil { + return nil, err + } + metricsClient, err := metricsv1beta1.NewForConfig(cfg) + if err != nil { + return nil, err + } + return &AccessControlClientset{ + cfg: cfg, + delegate: clientSet, + discoveryClient: clientSet.DiscoveryClient, + metricsV1beta1: metricsClient, + staticConfig: staticConfig, + }, nil +} diff --git a/pkg 2/kubernetes/accesscontrol_restmapper.go b/pkg 2/kubernetes/accesscontrol_restmapper.go new file mode 100644 index 00000000..06269480 --- /dev/null +++ b/pkg 2/kubernetes/accesscontrol_restmapper.go @@ -0,0 +1,80 @@ +package kubernetes + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/restmapper" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +type AccessControlRESTMapper struct { + delegate *restmapper.DeferredDiscoveryRESTMapper + staticConfig *config.StaticConfig // TODO: maybe just store the denied resource slice +} + +var _ meta.RESTMapper = &AccessControlRESTMapper{} + +func (a AccessControlRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + gvk, err := a.delegate.KindFor(resource) + if err != nil { + return schema.GroupVersionKind{}, err + } + if !isAllowed(a.staticConfig, &gvk) { + return schema.GroupVersionKind{}, isNotAllowedError(&gvk) + } + return gvk, nil +} + +func (a AccessControlRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { + gvks, err := a.delegate.KindsFor(resource) + if err != nil { + return nil, err + } + for i := range gvks { + if !isAllowed(a.staticConfig, &gvks[i]) { + return nil, isNotAllowedError(&gvks[i]) + } + } + return gvks, nil +} + +func (a AccessControlRESTMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { + return a.delegate.ResourceFor(input) +} + +func (a AccessControlRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { + return a.delegate.ResourcesFor(input) +} + +func (a AccessControlRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { + for _, version := range versions { + gvk := &schema.GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + } + return a.delegate.RESTMapping(gk, versions...) +} + +func (a AccessControlRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { + for _, version := range versions { + gvk := &schema.GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind} + if !isAllowed(a.staticConfig, gvk) { + return nil, isNotAllowedError(gvk) + } + } + return a.delegate.RESTMappings(gk, versions...) +} + +func (a AccessControlRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { + return a.delegate.ResourceSingularizer(resource) +} + +func (a AccessControlRESTMapper) Reset() { + a.delegate.Reset() +} + +func NewAccessControlRESTMapper(delegate *restmapper.DeferredDiscoveryRESTMapper, staticConfig *config.StaticConfig) *AccessControlRESTMapper { + return &AccessControlRESTMapper{delegate: delegate, staticConfig: staticConfig} +} diff --git a/pkg 2/kubernetes/configuration.go b/pkg 2/kubernetes/configuration.go new file mode 100644 index 00000000..df88530f --- /dev/null +++ b/pkg 2/kubernetes/configuration.go @@ -0,0 +1,115 @@ +package kubernetes + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/tools/clientcmd/api/latest" +) + +// InClusterConfig is a variable that holds the function to get the in-cluster config +// Exposed for testing +var InClusterConfig = func() (*rest.Config, error) { + // TODO use kubernetes.default.svc instead of resolved server + // Currently running into: `http: server gave HTTP response to HTTPS client` + inClusterConfig, err := rest.InClusterConfig() + if inClusterConfig != nil { + inClusterConfig.Host = "https://kubernetes.default.svc" + } + return inClusterConfig, err +} + +// resolveKubernetesConfigurations resolves the required kubernetes configurations and sets them in the Kubernetes struct +func resolveKubernetesConfigurations(kubernetes *Manager) error { + // Always set clientCmdConfig + pathOptions := clientcmd.NewDefaultPathOptions() + if kubernetes.staticConfig.KubeConfig != "" { + pathOptions.LoadingRules.ExplicitPath = kubernetes.staticConfig.KubeConfig + } + kubernetes.clientCmdConfig = clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + pathOptions.LoadingRules, + &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: ""}}) + var err error + if kubernetes.IsInCluster() { + kubernetes.cfg, err = InClusterConfig() + if err == nil && kubernetes.cfg != nil { + return nil + } + } + // Out of cluster + kubernetes.cfg, err = kubernetes.clientCmdConfig.ClientConfig() + if kubernetes.cfg != nil && kubernetes.cfg.UserAgent == "" { + kubernetes.cfg.UserAgent = rest.DefaultKubernetesUserAgent() + } + return err +} + +func (m *Manager) IsInCluster() bool { + if m.staticConfig.KubeConfig != "" { + return false + } + cfg, err := InClusterConfig() + return err == nil && cfg != nil +} + +func (m *Manager) configuredNamespace() string { + if ns, _, nsErr := m.clientCmdConfig.Namespace(); nsErr == nil { + return ns + } + return "" +} + +func (m *Manager) NamespaceOrDefault(namespace string) string { + if namespace == "" { + return m.configuredNamespace() + } + return namespace +} + +func (k *Kubernetes) NamespaceOrDefault(namespace string) string { + return k.manager.NamespaceOrDefault(namespace) +} + +// ToRESTConfig returns the rest.Config object (genericclioptions.RESTClientGetter) +func (m *Manager) ToRESTConfig() (*rest.Config, error) { + return m.cfg, nil +} + +// ToRawKubeConfigLoader returns the clientcmd.ClientConfig object (genericclioptions.RESTClientGetter) +func (m *Manager) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return m.clientCmdConfig +} + +func (m *Manager) ConfigurationView(minify bool) (runtime.Object, error) { + var cfg clientcmdapi.Config + var err error + if m.IsInCluster() { + cfg = *clientcmdapi.NewConfig() + cfg.Clusters["cluster"] = &clientcmdapi.Cluster{ + Server: m.cfg.Host, + InsecureSkipTLSVerify: m.cfg.Insecure, + } + cfg.AuthInfos["user"] = &clientcmdapi.AuthInfo{ + Token: m.cfg.BearerToken, + } + cfg.Contexts["context"] = &clientcmdapi.Context{ + Cluster: "cluster", + AuthInfo: "user", + } + cfg.CurrentContext = "context" + } else if cfg, err = m.clientCmdConfig.RawConfig(); err != nil { + return nil, err + } + if minify { + if err = clientcmdapi.MinifyConfig(&cfg); err != nil { + return nil, err + } + } + //nolint:staticcheck + if err = clientcmdapi.FlattenConfig(&cfg); err != nil { + // ignore error + //return "", err + } + return latest.Scheme.ConvertToVersion(&cfg, latest.ExternalVersion) +} diff --git a/pkg 2/kubernetes/configuration_test.go b/pkg 2/kubernetes/configuration_test.go new file mode 100644 index 00000000..084b99d7 --- /dev/null +++ b/pkg 2/kubernetes/configuration_test.go @@ -0,0 +1,155 @@ +package kubernetes + +import ( + "errors" + "os" + "path" + "runtime" + "strings" + "testing" + + "k8s.io/client-go/rest" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +func TestKubernetes_IsInCluster(t *testing.T) { + t.Run("with explicit kubeconfig", func(t *testing.T) { + m := Manager{ + staticConfig: &config.StaticConfig{ + KubeConfig: "kubeconfig", + }, + } + if m.IsInCluster() { + t.Errorf("expected not in cluster, got in cluster") + } + }) + t.Run("with empty kubeconfig and in cluster", func(t *testing.T) { + originalFunction := InClusterConfig + InClusterConfig = func() (*rest.Config, error) { + return &rest.Config{}, nil + } + defer func() { + InClusterConfig = originalFunction + }() + m := Manager{ + staticConfig: &config.StaticConfig{ + KubeConfig: "", + }, + } + if !m.IsInCluster() { + t.Errorf("expected in cluster, got not in cluster") + } + }) + t.Run("with empty kubeconfig and not in cluster (empty)", func(t *testing.T) { + originalFunction := InClusterConfig + InClusterConfig = func() (*rest.Config, error) { + return nil, nil + } + defer func() { + InClusterConfig = originalFunction + }() + m := Manager{ + staticConfig: &config.StaticConfig{ + KubeConfig: "", + }, + } + if m.IsInCluster() { + t.Errorf("expected not in cluster, got in cluster") + } + }) + t.Run("with empty kubeconfig and not in cluster (error)", func(t *testing.T) { + originalFunction := InClusterConfig + InClusterConfig = func() (*rest.Config, error) { + return nil, errors.New("error") + } + defer func() { + InClusterConfig = originalFunction + }() + m := Manager{ + staticConfig: &config.StaticConfig{ + KubeConfig: "", + }, + } + if m.IsInCluster() { + t.Errorf("expected not in cluster, got in cluster") + } + }) +} + +func TestKubernetes_ResolveKubernetesConfigurations_Explicit(t *testing.T) { + t.Run("with missing file", func(t *testing.T) { + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { + t.Skip("Skipping test on non-linux platforms") + } + tempDir := t.TempDir() + m := Manager{staticConfig: &config.StaticConfig{ + KubeConfig: path.Join(tempDir, "config"), + }} + err := resolveKubernetesConfigurations(&m) + if err == nil { + t.Errorf("expected error, got nil") + } + if !errors.Is(err, os.ErrNotExist) { + t.Errorf("expected file not found error, got %v", err) + } + if !strings.HasSuffix(err.Error(), ": no such file or directory") { + t.Errorf("expected file not found error, got %v", err) + } + }) + t.Run("with empty file", func(t *testing.T) { + tempDir := t.TempDir() + kubeconfigPath := path.Join(tempDir, "config") + if err := os.WriteFile(kubeconfigPath, []byte(""), 0644); err != nil { + t.Fatalf("failed to create kubeconfig file: %v", err) + } + m := Manager{staticConfig: &config.StaticConfig{ + KubeConfig: kubeconfigPath, + }} + err := resolveKubernetesConfigurations(&m) + if err == nil { + t.Errorf("expected error, got nil") + } + if !strings.Contains(err.Error(), "no configuration has been provided") { + t.Errorf("expected no kubeconfig error, got %v", err) + } + }) + t.Run("with valid file", func(t *testing.T) { + tempDir := t.TempDir() + kubeconfigPath := path.Join(tempDir, "config") + kubeconfigContent := ` +apiVersion: v1 +kind: Config +clusters: +- cluster: + server: https://example.com + name: example-cluster +contexts: +- context: + cluster: example-cluster + user: example-user + name: example-context +current-context: example-context +users: +- name: example-user + user: + token: example-token +` + if err := os.WriteFile(kubeconfigPath, []byte(kubeconfigContent), 0644); err != nil { + t.Fatalf("failed to create kubeconfig file: %v", err) + } + m := Manager{staticConfig: &config.StaticConfig{ + KubeConfig: kubeconfigPath, + }} + err := resolveKubernetesConfigurations(&m) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if m.cfg == nil { + t.Errorf("expected non-nil config, got nil") + } + if m.cfg.Host != "https://example.com" { + t.Errorf("expected host https://example.com, got %s", m.cfg.Host) + } + }) +} diff --git a/pkg 2/kubernetes/events.go b/pkg 2/kubernetes/events.go new file mode 100644 index 00000000..e40720a3 --- /dev/null +++ b/pkg 2/kubernetes/events.go @@ -0,0 +1,51 @@ +package kubernetes + +import ( + "context" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "strings" +) + +func (k *Kubernetes) EventsList(ctx context.Context, namespace string) ([]map[string]any, error) { + var eventMap []map[string]any + raw, err := k.ResourcesList(ctx, &schema.GroupVersionKind{ + Group: "", Version: "v1", Kind: "Event", + }, namespace, ResourceListOptions{}) + if err != nil { + return eventMap, err + } + unstructuredList := raw.(*unstructured.UnstructuredList) + if len(unstructuredList.Items) == 0 { + return eventMap, nil + } + for _, item := range unstructuredList.Items { + event := &v1.Event{} + if err = runtime.DefaultUnstructuredConverter.FromUnstructured(item.Object, event); err != nil { + return eventMap, err + } + timestamp := event.EventTime.Time + if timestamp.IsZero() && event.Series != nil { + timestamp = event.Series.LastObservedTime.Time + } else if timestamp.IsZero() && event.Count > 1 { + timestamp = event.LastTimestamp.Time + } else if timestamp.IsZero() { + timestamp = event.FirstTimestamp.Time + } + eventMap = append(eventMap, map[string]any{ + "Namespace": event.Namespace, + "Timestamp": timestamp.String(), + "Type": event.Type, + "Reason": event.Reason, + "InvolvedObject": map[string]string{ + "apiVersion": event.InvolvedObject.APIVersion, + "Kind": event.InvolvedObject.Kind, + "Name": event.InvolvedObject.Name, + }, + "Message": strings.TrimSpace(event.Message), + }) + } + return eventMap, nil +} diff --git a/pkg 2/kubernetes/impersonate_roundtripper.go b/pkg 2/kubernetes/impersonate_roundtripper.go new file mode 100644 index 00000000..a2c15bf2 --- /dev/null +++ b/pkg 2/kubernetes/impersonate_roundtripper.go @@ -0,0 +1,17 @@ +package kubernetes + +import "net/http" + +// nolint:unused +type impersonateRoundTripper struct { + delegate http.RoundTripper +} + +// nolint:unused +func (irt *impersonateRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + // TODO: Solution won't work with discoveryclient which uses context.TODO() instead of the passed-in context + if v, ok := req.Context().Value(OAuthAuthorizationHeader).(string); ok { + req.Header.Set("Authorization", v) + } + return irt.delegate.RoundTrip(req) +} diff --git a/pkg 2/kubernetes/kubernetes.go b/pkg 2/kubernetes/kubernetes.go new file mode 100644 index 00000000..db0ac542 --- /dev/null +++ b/pkg 2/kubernetes/kubernetes.go @@ -0,0 +1,214 @@ +package kubernetes + +import ( + "context" + "errors" + "strings" + + "k8s.io/apimachinery/pkg/runtime" + + "github.com/fsnotify/fsnotify" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + "k8s.io/client-go/discovery/cached/memory" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/klog/v2" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/helm" + + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" +) + +type HeaderKey string + +const ( + CustomAuthorizationHeader = HeaderKey("kubernetes-authorization") + OAuthAuthorizationHeader = HeaderKey("Authorization") + + CustomUserAgent = "kubernetes-mcp-server/bearer-token-auth" +) + +type CloseWatchKubeConfig func() error + +type Kubernetes struct { + manager *Manager +} + +type Manager struct { + cfg *rest.Config + clientCmdConfig clientcmd.ClientConfig + discoveryClient discovery.CachedDiscoveryInterface + accessControlClientSet *AccessControlClientset + accessControlRESTMapper *AccessControlRESTMapper + dynamicClient *dynamic.DynamicClient + + staticConfig *config.StaticConfig + CloseWatchKubeConfig CloseWatchKubeConfig +} + +var Scheme = scheme.Scheme +var ParameterCodec = runtime.NewParameterCodec(Scheme) + +var _ helm.Kubernetes = &Manager{} + +func NewManager(config *config.StaticConfig) (*Manager, error) { + k8s := &Manager{ + staticConfig: config, + } + if err := resolveKubernetesConfigurations(k8s); err != nil { + return nil, err + } + // TODO: Won't work because not all client-go clients use the shared context (e.g. discovery client uses context.TODO()) + //k8s.cfg.Wrap(func(original http.RoundTripper) http.RoundTripper { + // return &impersonateRoundTripper{original} + //}) + var err error + k8s.accessControlClientSet, err = NewAccessControlClientset(k8s.cfg, k8s.staticConfig) + if err != nil { + return nil, err + } + k8s.discoveryClient = memory.NewMemCacheClient(k8s.accessControlClientSet.DiscoveryClient()) + k8s.accessControlRESTMapper = NewAccessControlRESTMapper( + restmapper.NewDeferredDiscoveryRESTMapper(k8s.discoveryClient), + k8s.staticConfig, + ) + k8s.dynamicClient, err = dynamic.NewForConfig(k8s.cfg) + if err != nil { + return nil, err + } + return k8s, nil +} + +func (m *Manager) WatchKubeConfig(onKubeConfigChange func() error) { + if m.clientCmdConfig == nil { + return + } + kubeConfigFiles := m.clientCmdConfig.ConfigAccess().GetLoadingPrecedence() + if len(kubeConfigFiles) == 0 { + return + } + watcher, err := fsnotify.NewWatcher() + if err != nil { + return + } + for _, file := range kubeConfigFiles { + _ = watcher.Add(file) + } + go func() { + for { + select { + case _, ok := <-watcher.Events: + if !ok { + return + } + _ = onKubeConfigChange() + case _, ok := <-watcher.Errors: + if !ok { + return + } + } + } + }() + if m.CloseWatchKubeConfig != nil { + _ = m.CloseWatchKubeConfig() + } + m.CloseWatchKubeConfig = watcher.Close +} + +func (m *Manager) Close() { + if m.CloseWatchKubeConfig != nil { + _ = m.CloseWatchKubeConfig() + } +} + +func (m *Manager) GetAPIServerHost() string { + if m.cfg == nil { + return "" + } + return m.cfg.Host +} + +func (m *Manager) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + return m.discoveryClient, nil +} + +func (m *Manager) ToRESTMapper() (meta.RESTMapper, error) { + return m.accessControlRESTMapper, nil +} + +func (m *Manager) Derived(ctx context.Context) (*Kubernetes, error) { + authorization, ok := ctx.Value(OAuthAuthorizationHeader).(string) + if !ok || !strings.HasPrefix(authorization, "Bearer ") { + if m.staticConfig.RequireOAuth { + return nil, errors.New("oauth token required") + } + return &Kubernetes{manager: m}, nil + } + klog.V(5).Infof("%s header found (Bearer), using provided bearer token", OAuthAuthorizationHeader) + derivedCfg := &rest.Config{ + Host: m.cfg.Host, + APIPath: m.cfg.APIPath, + // Copy only server verification TLS settings (CA bundle and server name) + TLSClientConfig: rest.TLSClientConfig{ + Insecure: m.cfg.Insecure, + ServerName: m.cfg.ServerName, + CAFile: m.cfg.CAFile, + CAData: m.cfg.CAData, + }, + BearerToken: strings.TrimPrefix(authorization, "Bearer "), + // pass custom UserAgent to identify the client + UserAgent: CustomUserAgent, + QPS: m.cfg.QPS, + Burst: m.cfg.Burst, + Timeout: m.cfg.Timeout, + Impersonate: rest.ImpersonationConfig{}, + } + clientCmdApiConfig, err := m.clientCmdConfig.RawConfig() + if err != nil { + if m.staticConfig.RequireOAuth { + klog.Errorf("failed to get kubeconfig: %v", err) + return nil, errors.New("failed to get kubeconfig") + } + return &Kubernetes{manager: m}, nil + } + clientCmdApiConfig.AuthInfos = make(map[string]*clientcmdapi.AuthInfo) + derived := &Kubernetes{manager: &Manager{ + clientCmdConfig: clientcmd.NewDefaultClientConfig(clientCmdApiConfig, nil), + cfg: derivedCfg, + staticConfig: m.staticConfig, + }} + derived.manager.accessControlClientSet, err = NewAccessControlClientset(derived.manager.cfg, derived.manager.staticConfig) + if err != nil { + if m.staticConfig.RequireOAuth { + klog.Errorf("failed to get kubeconfig: %v", err) + return nil, errors.New("failed to get kubeconfig") + } + return &Kubernetes{manager: m}, nil + } + derived.manager.discoveryClient = memory.NewMemCacheClient(derived.manager.accessControlClientSet.DiscoveryClient()) + derived.manager.accessControlRESTMapper = NewAccessControlRESTMapper( + restmapper.NewDeferredDiscoveryRESTMapper(derived.manager.discoveryClient), + derived.manager.staticConfig, + ) + derived.manager.dynamicClient, err = dynamic.NewForConfig(derived.manager.cfg) + if err != nil { + if m.staticConfig.RequireOAuth { + klog.Errorf("failed to initialize dynamic client: %v", err) + return nil, errors.New("failed to initialize dynamic client") + } + return &Kubernetes{manager: m}, nil + } + return derived, nil +} + +func (k *Kubernetes) NewHelm() *helm.Helm { + // This is a derived Kubernetes, so it already has the Helm initialized + return helm.NewHelm(k.manager) +} diff --git a/pkg 2/kubernetes/kubernetes_test.go b/pkg 2/kubernetes/kubernetes_test.go new file mode 100644 index 00000000..2051ed48 --- /dev/null +++ b/pkg 2/kubernetes/kubernetes_test.go @@ -0,0 +1,316 @@ +package kubernetes + +import ( + "context" + "os" + "path" + "testing" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +func TestManager_Derived(t *testing.T) { + // Create a temporary kubeconfig file for testing + tempDir := t.TempDir() + kubeconfigPath := path.Join(tempDir, "config") + kubeconfigContent := ` +apiVersion: v1 +kind: Config +clusters: +- cluster: + server: https://test-cluster.example.com + name: test-cluster +contexts: +- context: + cluster: test-cluster + user: test-user + name: test-context +current-context: test-context +users: +- name: test-user + user: + username: test-username + password: test-password +` + if err := os.WriteFile(kubeconfigPath, []byte(kubeconfigContent), 0644); err != nil { + t.Fatalf("failed to create kubeconfig file: %v", err) + } + + t.Run("without authorization header returns original manager", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + ctx := context.Background() + derived, err := testManager.Derived(ctx) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + + if derived.manager != testManager { + t.Errorf("expected original manager, got different manager") + } + }) + + t.Run("with invalid authorization header returns original manager", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "invalid-token") + derived, err := testManager.Derived(ctx) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + + if derived.manager != testManager { + t.Errorf("expected original manager, got different manager") + } + }) + + t.Run("with valid bearer token creates derived manager with correct configuration", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + testBearerToken := "test-bearer-token-123" + ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "Bearer "+testBearerToken) + derived, err := testManager.Derived(ctx) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + + if derived.manager == testManager { + t.Errorf("expected new derived manager, got original manager") + } + + if derived.manager.staticConfig != testStaticConfig { + t.Errorf("staticConfig not properly wired to derived manager") + } + + derivedCfg := derived.manager.cfg + if derivedCfg == nil { + t.Fatalf("derived config is nil") + } + + originalCfg := testManager.cfg + if derivedCfg.Host != originalCfg.Host { + t.Errorf("expected Host %s, got %s", originalCfg.Host, derivedCfg.Host) + } + if derivedCfg.APIPath != originalCfg.APIPath { + t.Errorf("expected APIPath %s, got %s", originalCfg.APIPath, derivedCfg.APIPath) + } + if derivedCfg.QPS != originalCfg.QPS { + t.Errorf("expected QPS %f, got %f", originalCfg.QPS, derivedCfg.QPS) + } + if derivedCfg.Burst != originalCfg.Burst { + t.Errorf("expected Burst %d, got %d", originalCfg.Burst, derivedCfg.Burst) + } + if derivedCfg.Timeout != originalCfg.Timeout { + t.Errorf("expected Timeout %v, got %v", originalCfg.Timeout, derivedCfg.Timeout) + } + + if derivedCfg.Insecure != originalCfg.Insecure { + t.Errorf("expected TLS Insecure %v, got %v", originalCfg.Insecure, derivedCfg.Insecure) + } + if derivedCfg.ServerName != originalCfg.ServerName { + t.Errorf("expected TLS ServerName %s, got %s", originalCfg.ServerName, derivedCfg.ServerName) + } + if derivedCfg.CAFile != originalCfg.CAFile { + t.Errorf("expected TLS CAFile %s, got %s", originalCfg.CAFile, derivedCfg.CAFile) + } + if string(derivedCfg.CAData) != string(originalCfg.CAData) { + t.Errorf("expected TLS CAData %s, got %s", string(originalCfg.CAData), string(derivedCfg.CAData)) + } + + if derivedCfg.BearerToken != testBearerToken { + t.Errorf("expected BearerToken %s, got %s", testBearerToken, derivedCfg.BearerToken) + } + if derivedCfg.UserAgent != CustomUserAgent { + t.Errorf("expected UserAgent %s, got %s", CustomUserAgent, derivedCfg.UserAgent) + } + + // Verify that sensitive fields are NOT copied to prevent credential leakage + // The derived config should only use the bearer token from the Authorization header + // and not inherit any authentication credentials from the original kubeconfig + if derivedCfg.CertFile != "" { + t.Errorf("expected TLS CertFile to be empty, got %s", derivedCfg.CertFile) + } + if derivedCfg.KeyFile != "" { + t.Errorf("expected TLS KeyFile to be empty, got %s", derivedCfg.KeyFile) + } + if len(derivedCfg.CertData) != 0 { + t.Errorf("expected TLS CertData to be empty, got %v", derivedCfg.CertData) + } + if len(derivedCfg.KeyData) != 0 { + t.Errorf("expected TLS KeyData to be empty, got %v", derivedCfg.KeyData) + } + + if derivedCfg.Username != "" { + t.Errorf("expected Username to be empty, got %s", derivedCfg.Username) + } + if derivedCfg.Password != "" { + t.Errorf("expected Password to be empty, got %s", derivedCfg.Password) + } + if derivedCfg.AuthProvider != nil { + t.Errorf("expected AuthProvider to be nil, got %v", derivedCfg.AuthProvider) + } + if derivedCfg.ExecProvider != nil { + t.Errorf("expected ExecProvider to be nil, got %v", derivedCfg.ExecProvider) + } + if derivedCfg.BearerTokenFile != "" { + t.Errorf("expected BearerTokenFile to be empty, got %s", derivedCfg.BearerTokenFile) + } + if derivedCfg.Impersonate.UserName != "" { + t.Errorf("expected Impersonate.UserName to be empty, got %s", derivedCfg.Impersonate.UserName) + } + + // Verify that the original manager still has the sensitive data + if originalCfg.Username == "" && originalCfg.Password == "" { + t.Logf("original kubeconfig shouldn't be modified") + } + + // Verify that the derived manager has proper clients initialized + if derived.manager.accessControlClientSet == nil { + t.Error("expected accessControlClientSet to be initialized") + } + if derived.manager.accessControlClientSet.staticConfig != testStaticConfig { + t.Errorf("staticConfig not properly wired to derived manager") + } + if derived.manager.discoveryClient == nil { + t.Error("expected discoveryClient to be initialized") + } + if derived.manager.accessControlRESTMapper == nil { + t.Error("expected accessControlRESTMapper to be initialized") + } + if derived.manager.accessControlRESTMapper.staticConfig != testStaticConfig { + t.Errorf("staticConfig not properly wired to derived manager") + } + if derived.manager.dynamicClient == nil { + t.Error("expected dynamicClient to be initialized") + } + }) + + t.Run("with RequireOAuth=true and no authorization header returns oauth token required error", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + RequireOAuth: true, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + ctx := context.Background() + derived, err := testManager.Derived(ctx) + if err == nil { + t.Fatal("expected error for missing oauth token, got nil") + } + if err.Error() != "oauth token required" { + t.Fatalf("expected error 'oauth token required', got %s", err.Error()) + } + if derived != nil { + t.Error("expected nil derived manager when oauth token required") + } + }) + + t.Run("with RequireOAuth=true and invalid authorization header returns oauth token required error", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + RequireOAuth: true, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "invalid-token") + derived, err := testManager.Derived(ctx) + if err == nil { + t.Fatal("expected error for invalid oauth token, got nil") + } + if err.Error() != "oauth token required" { + t.Fatalf("expected error 'oauth token required', got %s", err.Error()) + } + if derived != nil { + t.Error("expected nil derived manager when oauth token required") + } + }) + + t.Run("with RequireOAuth=true and valid bearer token creates derived manager", func(t *testing.T) { + testStaticConfig := &config.StaticConfig{ + KubeConfig: kubeconfigPath, + RequireOAuth: true, + DisabledTools: []string{"configuration_view"}, + DeniedResources: []config.GroupVersionKind{ + {Group: "apps", Version: "v1", Kind: "Deployment"}, + }, + } + + testManager, err := NewManager(testStaticConfig) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + defer testManager.Close() + testBearerToken := "test-bearer-token-123" + ctx := context.WithValue(context.Background(), OAuthAuthorizationHeader, "Bearer "+testBearerToken) + derived, err := testManager.Derived(ctx) + if err != nil { + t.Fatalf("failed to create manager: %v", err) + } + + if derived.manager == testManager { + t.Error("expected new derived manager, got original manager") + } + + if derived.manager.staticConfig != testStaticConfig { + t.Error("staticConfig not properly wired to derived manager") + } + + derivedCfg := derived.manager.cfg + if derivedCfg == nil { + t.Fatal("derived config is nil") + } + + if derivedCfg.BearerToken != testBearerToken { + t.Errorf("expected BearerToken %s, got %s", testBearerToken, derivedCfg.BearerToken) + } + }) +} diff --git a/pkg 2/kubernetes/namespaces.go b/pkg 2/kubernetes/namespaces.go new file mode 100644 index 00000000..8c191c1e --- /dev/null +++ b/pkg 2/kubernetes/namespaces.go @@ -0,0 +1,19 @@ +package kubernetes + +import ( + "context" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func (k *Kubernetes) NamespacesList(ctx context.Context, options ResourceListOptions) (runtime.Unstructured, error) { + return k.ResourcesList(ctx, &schema.GroupVersionKind{ + Group: "", Version: "v1", Kind: "Namespace", + }, "", options) +} + +func (k *Kubernetes) ProjectsList(ctx context.Context, options ResourceListOptions) (runtime.Unstructured, error) { + return k.ResourcesList(ctx, &schema.GroupVersionKind{ + Group: "project.openshift.io", Version: "v1", Kind: "Project", + }, "", options) +} diff --git a/pkg 2/kubernetes/openshift.go b/pkg 2/kubernetes/openshift.go new file mode 100644 index 00000000..e94f9875 --- /dev/null +++ b/pkg 2/kubernetes/openshift.go @@ -0,0 +1,16 @@ +package kubernetes + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func (m *Manager) IsOpenShift(_ context.Context) bool { + // This method should be fast and not block (it's called at startup) + _, err := m.discoveryClient.ServerResourcesForGroupVersion(schema.GroupVersion{ + Group: "project.openshift.io", + Version: "v1", + }.String()) + return err == nil +} diff --git a/pkg 2/kubernetes/pods.go b/pkg 2/kubernetes/pods.go new file mode 100644 index 00000000..b6a12447 --- /dev/null +++ b/pkg 2/kubernetes/pods.go @@ -0,0 +1,251 @@ +package kubernetes + +import ( + "bytes" + "context" + "errors" + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + labelutil "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/client-go/tools/remotecommand" + "k8s.io/metrics/pkg/apis/metrics" + metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1" + + "github.com/containers/kubernetes-mcp-server/pkg/version" +) + +type PodsTopOptions struct { + metav1.ListOptions + AllNamespaces bool + Namespace string + Name string +} + +func (k *Kubernetes) PodsListInAllNamespaces(ctx context.Context, options ResourceListOptions) (runtime.Unstructured, error) { + return k.ResourcesList(ctx, &schema.GroupVersionKind{ + Group: "", Version: "v1", Kind: "Pod", + }, "", options) +} + +func (k *Kubernetes) PodsListInNamespace(ctx context.Context, namespace string, options ResourceListOptions) (runtime.Unstructured, error) { + return k.ResourcesList(ctx, &schema.GroupVersionKind{ + Group: "", Version: "v1", Kind: "Pod", + }, namespace, options) +} + +func (k *Kubernetes) PodsGet(ctx context.Context, namespace, name string) (*unstructured.Unstructured, error) { + return k.ResourcesGet(ctx, &schema.GroupVersionKind{ + Group: "", Version: "v1", Kind: "Pod", + }, k.NamespaceOrDefault(namespace), name) +} + +func (k *Kubernetes) PodsDelete(ctx context.Context, namespace, name string) (string, error) { + namespace = k.NamespaceOrDefault(namespace) + pod, err := k.ResourcesGet(ctx, &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}, namespace, name) + if err != nil { + return "", err + } + + isManaged := pod.GetLabels()[AppKubernetesManagedBy] == version.BinaryName + managedLabelSelector := labelutil.Set{ + AppKubernetesManagedBy: version.BinaryName, + AppKubernetesName: pod.GetLabels()[AppKubernetesName], + }.AsSelector() + + // Delete managed service + if isManaged { + services, err := k.manager.accessControlClientSet.Services(namespace) + if err != nil { + return "", err + } + if sl, _ := services.List(ctx, metav1.ListOptions{ + LabelSelector: managedLabelSelector.String(), + }); sl != nil { + for _, svc := range sl.Items { + _ = services.Delete(ctx, svc.Name, metav1.DeleteOptions{}) + } + } + } + + // Delete managed Route + if isManaged && k.supportsGroupVersion("route.openshift.io/v1") { + routeResources := k.manager.dynamicClient. + Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}). + Namespace(namespace) + if rl, _ := routeResources.List(ctx, metav1.ListOptions{ + LabelSelector: managedLabelSelector.String(), + }); rl != nil { + for _, route := range rl.Items { + _ = routeResources.Delete(ctx, route.GetName(), metav1.DeleteOptions{}) + } + } + + } + return "Pod deleted successfully", + k.ResourcesDelete(ctx, &schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}, namespace, name) +} + +func (k *Kubernetes) PodsLog(ctx context.Context, namespace, name, container string) (string, error) { + tailLines := int64(256) + pods, err := k.manager.accessControlClientSet.Pods(k.NamespaceOrDefault(namespace)) + if err != nil { + return "", err + } + req := pods.GetLogs(name, &v1.PodLogOptions{ + TailLines: &tailLines, + Container: container, + }) + res := req.Do(ctx) + if res.Error() != nil { + return "", res.Error() + } + rawData, err := res.Raw() + if err != nil { + return "", err + } + return string(rawData), nil +} + +func (k *Kubernetes) PodsRun(ctx context.Context, namespace, name, image string, port int32) ([]*unstructured.Unstructured, error) { + if name == "" { + name = version.BinaryName + "-run-" + rand.String(5) + } + labels := map[string]string{ + AppKubernetesName: name, + AppKubernetesComponent: name, + AppKubernetesManagedBy: version.BinaryName, + AppKubernetesPartOf: version.BinaryName + "-run-sandbox", + } + // NewPod + var resources []any + pod := &v1.Pod{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}, + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: k.NamespaceOrDefault(namespace), Labels: labels}, + Spec: v1.PodSpec{Containers: []v1.Container{{ + Name: name, + Image: image, + ImagePullPolicy: v1.PullAlways, + }}}, + } + resources = append(resources, pod) + if port > 0 { + pod.Spec.Containers[0].Ports = []v1.ContainerPort{{ContainerPort: port}} + resources = append(resources, &v1.Service{ + TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"}, + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: k.NamespaceOrDefault(namespace), Labels: labels}, + Spec: v1.ServiceSpec{ + Selector: labels, + Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{{Port: port, TargetPort: intstr.FromInt32(port)}}, + }, + }) + } + if port > 0 && k.supportsGroupVersion("route.openshift.io/v1") { + resources = append(resources, &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "route.openshift.io/v1", + "kind": "Route", + "metadata": map[string]interface{}{ + "name": name, + "namespace": k.NamespaceOrDefault(namespace), + "labels": labels, + }, + "spec": map[string]interface{}{ + "to": map[string]interface{}{ + "kind": "Service", + "name": name, + "weight": 100, + }, + "port": map[string]interface{}{ + "targetPort": intstr.FromInt32(port), + }, + "tls": map[string]interface{}{ + "termination": "edge", + "insecureEdgeTerminationPolicy": "Redirect", + }, + }, + }, + }) + + } + + // Convert the objects to Unstructured and reuse resourcesCreateOrUpdate functionality + converter := runtime.DefaultUnstructuredConverter + var toCreate []*unstructured.Unstructured + for _, obj := range resources { + m, err := converter.ToUnstructured(obj) + if err != nil { + return nil, err + } + u := &unstructured.Unstructured{} + if err = converter.FromUnstructured(m, u); err != nil { + return nil, err + } + toCreate = append(toCreate, u) + } + return k.resourcesCreateOrUpdate(ctx, toCreate) +} + +func (k *Kubernetes) PodsTop(ctx context.Context, options PodsTopOptions) (*metrics.PodMetricsList, error) { + // TODO, maybe move to mcp Tools setup and omit in case metrics aren't available in the target cluster + if !k.supportsGroupVersion(metrics.GroupName + "/" + metricsv1beta1api.SchemeGroupVersion.Version) { + return nil, errors.New("metrics API is not available") + } + namespace := options.Namespace + if options.AllNamespaces && namespace == "" { + namespace = "" + } else { + namespace = k.NamespaceOrDefault(namespace) + } + return k.manager.accessControlClientSet.PodsMetricses(ctx, namespace, options.Name, options.ListOptions) +} + +func (k *Kubernetes) PodsExec(ctx context.Context, namespace, name, container string, command []string) (string, error) { + namespace = k.NamespaceOrDefault(namespace) + pods, err := k.manager.accessControlClientSet.Pods(namespace) + if err != nil { + return "", err + } + pod, err := pods.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return "", err + } + // https://github.com/kubernetes/kubectl/blob/5366de04e168bcbc11f5e340d131a9ca8b7d0df4/pkg/cmd/exec/exec.go#L350-L352 + if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed { + return "", fmt.Errorf("cannot exec into a container in a completed pod; current phase is %s", pod.Status.Phase) + } + if container == "" { + container = pod.Spec.Containers[0].Name + } + podExecOptions := &v1.PodExecOptions{ + Container: container, + Command: command, + Stdout: true, + Stderr: true, + } + executor, err := k.manager.accessControlClientSet.PodsExec(namespace, name, podExecOptions) + if err != nil { + return "", err + } + stdout := bytes.NewBuffer(make([]byte, 0)) + stderr := bytes.NewBuffer(make([]byte, 0)) + if err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{ + Stdout: stdout, Stderr: stderr, Tty: false, + }); err != nil { + return "", err + } + if stdout.Len() > 0 { + return stdout.String(), nil + } + if stderr.Len() > 0 { + return stderr.String(), nil + } + return "", nil +} diff --git a/pkg 2/kubernetes/resources.go b/pkg 2/kubernetes/resources.go new file mode 100644 index 00000000..1f559e12 --- /dev/null +++ b/pkg 2/kubernetes/resources.go @@ -0,0 +1,209 @@ +package kubernetes + +import ( + "context" + "fmt" + "k8s.io/apimachinery/pkg/runtime" + "regexp" + "strings" + + "github.com/containers/kubernetes-mcp-server/pkg/version" + authv1 "k8s.io/api/authorization/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/yaml" +) + +const ( + AppKubernetesComponent = "app.kubernetes.io/component" + AppKubernetesManagedBy = "app.kubernetes.io/managed-by" + AppKubernetesName = "app.kubernetes.io/name" + AppKubernetesPartOf = "app.kubernetes.io/part-of" +) + +type ResourceListOptions struct { + metav1.ListOptions + AsTable bool +} + +func (k *Kubernetes) ResourcesList(ctx context.Context, gvk *schema.GroupVersionKind, namespace string, options ResourceListOptions) (runtime.Unstructured, error) { + gvr, err := k.resourceFor(gvk) + if err != nil { + return nil, err + } + + // Check if operation is allowed for all namespaces (applicable for namespaced resources) + isNamespaced, _ := k.isNamespaced(gvk) + if isNamespaced && !k.canIUse(ctx, gvr, namespace, "list") && namespace == "" { + namespace = k.manager.configuredNamespace() + } + if options.AsTable { + return k.resourcesListAsTable(ctx, gvk, gvr, namespace, options) + } + return k.manager.dynamicClient.Resource(*gvr).Namespace(namespace).List(ctx, options.ListOptions) +} + +func (k *Kubernetes) ResourcesGet(ctx context.Context, gvk *schema.GroupVersionKind, namespace, name string) (*unstructured.Unstructured, error) { + gvr, err := k.resourceFor(gvk) + if err != nil { + return nil, err + } + + // If it's a namespaced resource and namespace wasn't provided, try to use the default configured one + if namespaced, nsErr := k.isNamespaced(gvk); nsErr == nil && namespaced { + namespace = k.NamespaceOrDefault(namespace) + } + return k.manager.dynamicClient.Resource(*gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{}) +} + +func (k *Kubernetes) ResourcesCreateOrUpdate(ctx context.Context, resource string) ([]*unstructured.Unstructured, error) { + separator := regexp.MustCompile(`\r?\n---\r?\n`) + resources := separator.Split(resource, -1) + var parsedResources []*unstructured.Unstructured + for _, r := range resources { + var obj unstructured.Unstructured + if err := yaml.NewYAMLToJSONDecoder(strings.NewReader(r)).Decode(&obj); err != nil { + return nil, err + } + parsedResources = append(parsedResources, &obj) + } + return k.resourcesCreateOrUpdate(ctx, parsedResources) +} + +func (k *Kubernetes) ResourcesDelete(ctx context.Context, gvk *schema.GroupVersionKind, namespace, name string) error { + gvr, err := k.resourceFor(gvk) + if err != nil { + return err + } + + // If it's a namespaced resource and namespace wasn't provided, try to use the default configured one + if namespaced, nsErr := k.isNamespaced(gvk); nsErr == nil && namespaced { + namespace = k.NamespaceOrDefault(namespace) + } + return k.manager.dynamicClient.Resource(*gvr).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{}) +} + +// resourcesListAsTable retrieves a list of resources in a table format. +// It's almost identical to the dynamic.DynamicClient implementation, but it uses a specific Accept header to request the table format. +// dynamic.DynamicClient does not provide a way to set the HTTP header (TODO: create an issue to request this feature) +func (k *Kubernetes) resourcesListAsTable(ctx context.Context, gvk *schema.GroupVersionKind, gvr *schema.GroupVersionResource, namespace string, options ResourceListOptions) (runtime.Unstructured, error) { + var url []string + if len(gvr.Group) == 0 { + url = append(url, "api") + } else { + url = append(url, "apis", gvr.Group) + } + url = append(url, gvr.Version) + if len(namespace) > 0 { + url = append(url, "namespaces", namespace) + } + url = append(url, gvr.Resource) + var table metav1.Table + err := k.manager.discoveryClient.RESTClient(). + Get(). + SetHeader("Accept", strings.Join([]string{ + fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1.SchemeGroupVersion.Version, metav1.GroupName), + fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName), + "application/json", + }, ",")). + AbsPath(url...). + SpecificallyVersionedParams(&options.ListOptions, ParameterCodec, schema.GroupVersion{Version: "v1"}). + Do(ctx).Into(&table) + if err != nil { + return nil, err + } + // Add metav1.Table apiVersion and kind to the unstructured object (server may not return these fields) + table.SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("Table")) + // Add additional columns for fields that aren't returned by the server + table.ColumnDefinitions = append([]metav1.TableColumnDefinition{ + {Name: "apiVersion", Type: "string"}, + {Name: "kind", Type: "string"}, + }, table.ColumnDefinitions...) + for i := range table.Rows { + row := &table.Rows[i] + row.Cells = append([]interface{}{ + gvr.GroupVersion().String(), + gvk.Kind, + }, row.Cells...) + } + unstructuredObject, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&table) + return &unstructured.Unstructured{Object: unstructuredObject}, err +} + +func (k *Kubernetes) resourcesCreateOrUpdate(ctx context.Context, resources []*unstructured.Unstructured) ([]*unstructured.Unstructured, error) { + for i, obj := range resources { + gvk := obj.GroupVersionKind() + gvr, rErr := k.resourceFor(&gvk) + if rErr != nil { + return nil, rErr + } + + namespace := obj.GetNamespace() + // If it's a namespaced resource and namespace wasn't provided, try to use the default configured one + if namespaced, nsErr := k.isNamespaced(&gvk); nsErr == nil && namespaced { + namespace = k.NamespaceOrDefault(namespace) + } + resources[i], rErr = k.manager.dynamicClient.Resource(*gvr).Namespace(namespace).Apply(ctx, obj.GetName(), obj, metav1.ApplyOptions{ + FieldManager: version.BinaryName, + }) + if rErr != nil { + return nil, rErr + } + // Clear the cache to ensure the next operation is performed on the latest exposed APIs (will change after the CRD creation) + if gvk.Kind == "CustomResourceDefinition" { + k.manager.accessControlRESTMapper.Reset() + } + } + return resources, nil +} + +func (k *Kubernetes) resourceFor(gvk *schema.GroupVersionKind) (*schema.GroupVersionResource, error) { + m, err := k.manager.accessControlRESTMapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) + if err != nil { + return nil, err + } + return &m.Resource, nil +} + +func (k *Kubernetes) isNamespaced(gvk *schema.GroupVersionKind) (bool, error) { + apiResourceList, err := k.manager.discoveryClient.ServerResourcesForGroupVersion(gvk.GroupVersion().String()) + if err != nil { + return false, err + } + for _, apiResource := range apiResourceList.APIResources { + if apiResource.Kind == gvk.Kind { + return apiResource.Namespaced, nil + } + } + return false, nil +} + +func (k *Kubernetes) supportsGroupVersion(groupVersion string) bool { + if _, err := k.manager.discoveryClient.ServerResourcesForGroupVersion(groupVersion); err != nil { + return false + } + return true +} + +func (k *Kubernetes) canIUse(ctx context.Context, gvr *schema.GroupVersionResource, namespace, verb string) bool { + accessReviews, err := k.manager.accessControlClientSet.SelfSubjectAccessReviews() + if err != nil { + return false + } + response, err := accessReviews.Create(ctx, &authv1.SelfSubjectAccessReview{ + Spec: authv1.SelfSubjectAccessReviewSpec{ResourceAttributes: &authv1.ResourceAttributes{ + Namespace: namespace, + Verb: verb, + Group: gvr.Group, + Version: gvr.Version, + Resource: gvr.Resource, + }}, + }, metav1.CreateOptions{}) + if err != nil { + // TODO: maybe return the error too + return false + } + return response.Status.Allowed +} diff --git a/pkg 2/kubernetes/token.go b/pkg 2/kubernetes/token.go new file mode 100644 index 00000000..bac697c8 --- /dev/null +++ b/pkg 2/kubernetes/token.go @@ -0,0 +1,39 @@ +package kubernetes + +import ( + "context" + "fmt" + authenticationv1api "k8s.io/api/authentication/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (m *Manager) VerifyToken(ctx context.Context, token, audience string) (*authenticationv1api.UserInfo, []string, error) { + tokenReviewClient, err := m.accessControlClientSet.TokenReview() + if err != nil { + return nil, nil, err + } + tokenReview := &authenticationv1api.TokenReview{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "authentication.k8s.io/v1", + Kind: "TokenReview", + }, + Spec: authenticationv1api.TokenReviewSpec{ + Token: token, + Audiences: []string{audience}, + }, + } + + result, err := tokenReviewClient.Create(ctx, tokenReview, metav1.CreateOptions{}) + if err != nil { + return nil, nil, fmt.Errorf("failed to create token review: %v", err) + } + + if !result.Status.Authenticated { + if result.Status.Error != "" { + return nil, nil, fmt.Errorf("token authentication failed: %s", result.Status.Error) + } + return nil, nil, fmt.Errorf("token authentication failed") + } + + return &result.Status.User, result.Status.Audiences, nil +} diff --git a/pkg 2/mcp/common_test.go b/pkg 2/mcp/common_test.go new file mode 100644 index 00000000..8e4e49d3 --- /dev/null +++ b/pkg 2/mcp/common_test.go @@ -0,0 +1,421 @@ +package mcp + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + "net/http/httptest" + "os" + "path/filepath" + "runtime" + "strconv" + "testing" + "time" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/output" + "github.com/mark3labs/mcp-go/client" + "github.com/mark3labs/mcp-go/client/transport" + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + "github.com/pkg/errors" + "github.com/spf13/afero" + "golang.org/x/sync/errgroup" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apiextensionsv1spec "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" + toolswatch "k8s.io/client-go/tools/watch" + "k8s.io/klog/v2" + "k8s.io/klog/v2/textlogger" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/tools/setup-envtest/env" + "sigs.k8s.io/controller-runtime/tools/setup-envtest/remote" + "sigs.k8s.io/controller-runtime/tools/setup-envtest/store" + "sigs.k8s.io/controller-runtime/tools/setup-envtest/versions" + "sigs.k8s.io/controller-runtime/tools/setup-envtest/workflows" +) + +// envTest has an expensive setup, so we only want to do it once per entire test run. +var envTest *envtest.Environment +var envTestRestConfig *rest.Config +var envTestUser = envtest.User{Name: "test-user", Groups: []string{"test:users"}} + +func TestMain(m *testing.M) { + // Set up + envTestDir, err := store.DefaultStoreDir() + if err != nil { + panic(err) + } + envTestEnv := &env.Env{ + FS: afero.Afero{Fs: afero.NewOsFs()}, + Out: os.Stdout, + Client: &remote.HTTPClient{ + IndexURL: remote.DefaultIndexURL, + }, + Platform: versions.PlatformItem{ + Platform: versions.Platform{ + OS: runtime.GOOS, + Arch: runtime.GOARCH, + }, + }, + Version: versions.AnyVersion, + Store: store.NewAt(envTestDir), + } + envTestEnv.CheckCoherence() + workflows.Use{}.Do(envTestEnv) + versionDir := envTestEnv.Platform.BaseName(*envTestEnv.Version.AsConcrete()) + envTest = &envtest.Environment{ + BinaryAssetsDirectory: filepath.Join(envTestDir, "k8s", versionDir), + } + adminSystemMasterBaseConfig, _ := envTest.Start() + au, err := envTest.AddUser(envTestUser, adminSystemMasterBaseConfig) + if err != nil { + panic(err) + } + envTestRestConfig = au.Config() + + //Create test data as administrator + ctx := context.Background() + restoreAuth(ctx) + createTestData(ctx) + + // Test! + code := m.Run() + + // Tear down + if envTest != nil { + _ = envTest.Stop() + } + os.Exit(code) +} + +type mcpContext struct { + profile Profile + listOutput output.Output + logLevel int + + staticConfig *config.StaticConfig + clientOptions []transport.ClientOption + before func(*mcpContext) + after func(*mcpContext) + ctx context.Context + tempDir string + cancel context.CancelFunc + mcpServer *Server + mcpHttpServer *httptest.Server + mcpClient *client.Client + klogState klog.State + logBuffer bytes.Buffer +} + +func (c *mcpContext) beforeEach(t *testing.T) { + var err error + c.ctx, c.cancel = context.WithCancel(t.Context()) + c.tempDir = t.TempDir() + c.withKubeConfig(nil) + if c.profile == nil { + c.profile = &FullProfile{} + } + if c.listOutput == nil { + c.listOutput = output.Yaml + } + if c.staticConfig == nil { + c.staticConfig = &config.StaticConfig{ + ReadOnly: false, + DisableDestructive: false, + } + } + if c.before != nil { + c.before(c) + } + // Set up logging + c.klogState = klog.CaptureState() + flags := flag.NewFlagSet("test", flag.ContinueOnError) + klog.InitFlags(flags) + _ = flags.Set("v", strconv.Itoa(c.logLevel)) + klog.SetLogger(textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(c.logLevel), textlogger.Output(&c.logBuffer)))) + // MCP Server + if c.mcpServer, err = NewServer(Configuration{ + Profile: c.profile, + ListOutput: c.listOutput, + StaticConfig: c.staticConfig, + }); err != nil { + t.Fatal(err) + return + } + c.mcpHttpServer = server.NewTestServer(c.mcpServer.server, server.WithSSEContextFunc(contextFunc)) + if c.mcpClient, err = client.NewSSEMCPClient(c.mcpHttpServer.URL+"/sse", c.clientOptions...); err != nil { + t.Fatal(err) + return + } + // MCP Client + if err = c.mcpClient.Start(c.ctx); err != nil { + t.Fatal(err) + return + } + initRequest := mcp.InitializeRequest{} + initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION + initRequest.Params.ClientInfo = mcp.Implementation{Name: "test", Version: "1.33.7"} + _, err = c.mcpClient.Initialize(c.ctx, initRequest) + if err != nil { + t.Fatal(err) + return + } +} + +func (c *mcpContext) afterEach() { + if c.after != nil { + c.after(c) + } + c.cancel() + c.mcpServer.Close() + _ = c.mcpClient.Close() + c.mcpHttpServer.Close() + c.klogState.Restore() +} + +func testCase(t *testing.T, test func(c *mcpContext)) { + testCaseWithContext(t, &mcpContext{profile: &FullProfile{}}, test) +} + +func testCaseWithContext(t *testing.T, mcpCtx *mcpContext, test func(c *mcpContext)) { + mcpCtx.beforeEach(t) + defer mcpCtx.afterEach() + test(mcpCtx) +} + +// withKubeConfig sets up a fake kubeconfig in the temp directory based on the provided rest.Config +func (c *mcpContext) withKubeConfig(rc *rest.Config) *api.Config { + fakeConfig := api.NewConfig() + fakeConfig.Clusters["fake"] = api.NewCluster() + fakeConfig.Clusters["fake"].Server = "https://127.0.0.1:6443" + fakeConfig.Clusters["additional-cluster"] = api.NewCluster() + fakeConfig.AuthInfos["fake"] = api.NewAuthInfo() + fakeConfig.AuthInfos["additional-auth"] = api.NewAuthInfo() + if rc != nil { + fakeConfig.Clusters["fake"].Server = rc.Host + fakeConfig.Clusters["fake"].CertificateAuthorityData = rc.CAData + fakeConfig.AuthInfos["fake"].ClientKeyData = rc.KeyData + fakeConfig.AuthInfos["fake"].ClientCertificateData = rc.CertData + } + fakeConfig.Contexts["fake-context"] = api.NewContext() + fakeConfig.Contexts["fake-context"].Cluster = "fake" + fakeConfig.Contexts["fake-context"].AuthInfo = "fake" + fakeConfig.Contexts["additional-context"] = api.NewContext() + fakeConfig.Contexts["additional-context"].Cluster = "additional-cluster" + fakeConfig.Contexts["additional-context"].AuthInfo = "additional-auth" + fakeConfig.CurrentContext = "fake-context" + kubeConfig := filepath.Join(c.tempDir, "config") + _ = clientcmd.WriteToFile(*fakeConfig, kubeConfig) + _ = os.Setenv("KUBECONFIG", kubeConfig) + if c.mcpServer != nil { + if err := c.mcpServer.reloadKubernetesClient(); err != nil { + panic(err) + } + } + return fakeConfig +} + +// withEnvTest sets up the environment for kubeconfig to be used with envTest +func (c *mcpContext) withEnvTest() { + c.withKubeConfig(envTestRestConfig) +} + +// inOpenShift sets up the kubernetes environment to seem to be running OpenShift +func inOpenShift(c *mcpContext) { + c.withEnvTest() + crdTemplate := ` + { + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "CustomResourceDefinition", + "metadata": {"name": "%s"}, + "spec": { + "group": "%s", + "versions": [{ + "name": "v1","served": true,"storage": true, + "schema": {"openAPIV3Schema": {"type": "object","x-kubernetes-preserve-unknown-fields": true}} + }], + "scope": "%s", + "names": {"plural": "%s","singular": "%s","kind": "%s"} + } + }` + tasks, _ := errgroup.WithContext(c.ctx) + tasks.Go(func() error { + return c.crdApply(fmt.Sprintf(crdTemplate, "projects.project.openshift.io", "project.openshift.io", + "Cluster", "projects", "project", "Project")) + }) + tasks.Go(func() error { + return c.crdApply(fmt.Sprintf(crdTemplate, "routes.route.openshift.io", "route.openshift.io", + "Namespaced", "routes", "route", "Route")) + }) + if err := tasks.Wait(); err != nil { + panic(err) + } +} + +// inOpenShiftClear clears the kubernetes environment so it no longer seems to be running OpenShift +func inOpenShiftClear(c *mcpContext) { + tasks, _ := errgroup.WithContext(c.ctx) + tasks.Go(func() error { return c.crdDelete("projects.project.openshift.io") }) + tasks.Go(func() error { return c.crdDelete("routes.route.openshift.io") }) + if err := tasks.Wait(); err != nil { + panic(err) + } +} + +// newKubernetesClient creates a new Kubernetes client with the envTest kubeconfig +func (c *mcpContext) newKubernetesClient() *kubernetes.Clientset { + return kubernetes.NewForConfigOrDie(envTestRestConfig) +} + +// newApiExtensionsClient creates a new ApiExtensions client with the envTest kubeconfig +func (c *mcpContext) newApiExtensionsClient() *apiextensionsv1.ApiextensionsV1Client { + return apiextensionsv1.NewForConfigOrDie(envTestRestConfig) +} + +// crdApply creates a CRD from the provided resource string and waits for it to be established +func (c *mcpContext) crdApply(resource string) error { + apiExtensionsV1Client := c.newApiExtensionsClient() + var crd = &apiextensionsv1spec.CustomResourceDefinition{} + err := json.Unmarshal([]byte(resource), crd) + if err != nil { + return fmt.Errorf("failed to create CRD %v", err) + } + _, err = apiExtensionsV1Client.CustomResourceDefinitions().Create(c.ctx, crd, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("failed to create CRD %v", err) + } + c.crdWaitUntilReady(crd.Name) + return nil +} + +// crdDelete deletes a CRD by name and waits for it to be removed +func (c *mcpContext) crdDelete(name string) error { + apiExtensionsV1Client := c.newApiExtensionsClient() + err := apiExtensionsV1Client.CustomResourceDefinitions().Delete(c.ctx, name, metav1.DeleteOptions{ + GracePeriodSeconds: ptr.To(int64(0)), + }) + iteration := 0 + for iteration < 100 { + if _, derr := apiExtensionsV1Client.CustomResourceDefinitions().Get(c.ctx, name, metav1.GetOptions{}); derr != nil { + break + } + time.Sleep(5 * time.Millisecond) + iteration++ + } + if err != nil { + return errors.Wrap(err, "failed to delete CRD") + } + return nil +} + +// crdWaitUntilReady waits for a CRD to be established +func (c *mcpContext) crdWaitUntilReady(name string) { + watcher, err := c.newApiExtensionsClient().CustomResourceDefinitions().Watch(c.ctx, metav1.ListOptions{ + FieldSelector: "metadata.name=" + name, + }) + if err != nil { + panic(fmt.Errorf("failed to watch CRD %v", err)) + } + _, err = toolswatch.UntilWithoutRetry(c.ctx, watcher, func(event watch.Event) (bool, error) { + for _, c := range event.Object.(*apiextensionsv1spec.CustomResourceDefinition).Status.Conditions { + if c.Type == apiextensionsv1spec.Established && c.Status == apiextensionsv1spec.ConditionTrue { + return true, nil + } + } + return false, nil + }) + if err != nil { + panic(fmt.Errorf("failed to wait for CRD %v", err)) + } +} + +// callTool helper function to call a tool by name with arguments +func (c *mcpContext) callTool(name string, args map[string]interface{}) (*mcp.CallToolResult, error) { + callToolRequest := mcp.CallToolRequest{} + callToolRequest.Params.Name = name + callToolRequest.Params.Arguments = args + return c.mcpClient.CallTool(c.ctx, callToolRequest) +} + +func restoreAuth(ctx context.Context) { + kubernetesAdmin := kubernetes.NewForConfigOrDie(envTest.Config) + // Authorization + _, _ = kubernetesAdmin.RbacV1().ClusterRoles().Update(ctx, &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{Name: "allow-all"}, + Rules: []rbacv1.PolicyRule{{ + Verbs: []string{"*"}, + APIGroups: []string{"*"}, + Resources: []string{"*"}, + }}, + }, metav1.UpdateOptions{}) + _, _ = kubernetesAdmin.RbacV1().ClusterRoleBindings().Update(ctx, &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: "allow-all"}, + Subjects: []rbacv1.Subject{{Kind: "Group", Name: envTestUser.Groups[0]}}, + RoleRef: rbacv1.RoleRef{Kind: "ClusterRole", Name: "allow-all"}, + }, metav1.UpdateOptions{}) +} + +func createTestData(ctx context.Context) { + kubernetesAdmin := kubernetes.NewForConfigOrDie(envTestRestConfig) + // Namespaces + _, _ = kubernetesAdmin.CoreV1().Namespaces(). + Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-1"}}, metav1.CreateOptions{}) + _, _ = kubernetesAdmin.CoreV1().Namespaces(). + Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-2"}}, metav1.CreateOptions{}) + _, _ = kubernetesAdmin.CoreV1().Namespaces(). + Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-to-delete"}}, metav1.CreateOptions{}) + _, _ = kubernetesAdmin.CoreV1().Pods("default").Create(ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-pod-in-default", + Labels: map[string]string{"app": "nginx"}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "nginx", + Image: "nginx", + }, + }, + }, + }, metav1.CreateOptions{}) + // Pods for listing + _, _ = kubernetesAdmin.CoreV1().Pods("ns-1").Create(ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-pod-in-ns-1", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "nginx", + Image: "nginx", + }, + }, + }, + }, metav1.CreateOptions{}) + _, _ = kubernetesAdmin.CoreV1().Pods("ns-2").Create(ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-pod-in-ns-2", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "nginx", + Image: "nginx", + }, + }, + }, + }, metav1.CreateOptions{}) + _, _ = kubernetesAdmin.CoreV1().ConfigMaps("default"). + Create(ctx, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "a-configmap-to-delete"}}, metav1.CreateOptions{}) +} diff --git a/pkg 2/mcp/configuration.go b/pkg 2/mcp/configuration.go new file mode 100644 index 00000000..79ebaef4 --- /dev/null +++ b/pkg 2/mcp/configuration.go @@ -0,0 +1,46 @@ +package mcp + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + + "github.com/containers/kubernetes-mcp-server/pkg/output" +) + +func (s *Server) initConfiguration() []server.ServerTool { + tools := []server.ServerTool{ + {Tool: mcp.NewTool("configuration_view", + mcp.WithDescription("Get the current Kubernetes configuration content as a kubeconfig YAML"), + mcp.WithBoolean("minified", mcp.Description("Return a minified version of the configuration. "+ + "If set to true, keeps only the current-context and the relevant pieces of the configuration for that context. "+ + "If set to false, all contexts, clusters, auth-infos, and users are returned in the configuration. "+ + "(Optional, default true)")), + // Tool annotations + mcp.WithTitleAnnotation("Configuration: View"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.configurationView}, + } + return tools +} + +func (s *Server) configurationView(_ context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + minify := true + minified := ctr.GetArguments()["minified"] + if _, ok := minified.(bool); ok { + minify = minified.(bool) + } + ret, err := s.k.ConfigurationView(minify) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get configuration: %v", err)), nil + } + configurationYaml, err := output.MarshalYaml(ret) + if err != nil { + err = fmt.Errorf("failed to get configuration: %v", err) + } + return NewTextResult(configurationYaml, err), nil +} diff --git a/pkg 2/mcp/configuration_test.go b/pkg 2/mcp/configuration_test.go new file mode 100644 index 00000000..57fea486 --- /dev/null +++ b/pkg 2/mcp/configuration_test.go @@ -0,0 +1,178 @@ +package mcp + +import ( + "github.com/containers/kubernetes-mcp-server/pkg/kubernetes" + "github.com/mark3labs/mcp-go/mcp" + "k8s.io/client-go/rest" + v1 "k8s.io/client-go/tools/clientcmd/api/v1" + "sigs.k8s.io/yaml" + "testing" +) + +func TestConfigurationView(t *testing.T) { + testCase(t, func(c *mcpContext) { + toolResult, err := c.callTool("configuration_view", map[string]interface{}{}) + t.Run("configuration_view returns configuration", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + }) + var decoded *v1.Config + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("configuration_view has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("configuration_view returns current-context", func(t *testing.T) { + if decoded.CurrentContext != "fake-context" { + t.Errorf("fake-context not found: %v", decoded.CurrentContext) + } + }) + t.Run("configuration_view returns context info", func(t *testing.T) { + if len(decoded.Contexts) != 1 { + t.Errorf("invalid context count, expected 1, got %v", len(decoded.Contexts)) + } + if decoded.Contexts[0].Name != "fake-context" { + t.Errorf("fake-context not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.Cluster != "fake" { + t.Errorf("fake-cluster not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.AuthInfo != "fake" { + t.Errorf("fake-auth not found: %v", decoded.Contexts) + } + }) + t.Run("configuration_view returns cluster info", func(t *testing.T) { + if len(decoded.Clusters) != 1 { + t.Errorf("invalid cluster count, expected 1, got %v", len(decoded.Clusters)) + } + if decoded.Clusters[0].Name != "fake" { + t.Errorf("fake-cluster not found: %v", decoded.Clusters) + } + if decoded.Clusters[0].Cluster.Server != "https://127.0.0.1:6443" { + t.Errorf("fake-server not found: %v", decoded.Clusters) + } + }) + t.Run("configuration_view returns auth info", func(t *testing.T) { + if len(decoded.AuthInfos) != 1 { + t.Errorf("invalid auth info count, expected 1, got %v", len(decoded.AuthInfos)) + } + if decoded.AuthInfos[0].Name != "fake" { + t.Errorf("fake-auth not found: %v", decoded.AuthInfos) + } + }) + toolResult, err = c.callTool("configuration_view", map[string]interface{}{ + "minified": false, + }) + t.Run("configuration_view with minified=false returns configuration", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + }) + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("configuration_view with minified=false has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("configuration_view with minified=false returns additional context info", func(t *testing.T) { + if len(decoded.Contexts) != 2 { + t.Errorf("invalid context count, expected2, got %v", len(decoded.Contexts)) + } + if decoded.Contexts[0].Name != "additional-context" { + t.Errorf("additional-context not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.Cluster != "additional-cluster" { + t.Errorf("additional-cluster not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.AuthInfo != "additional-auth" { + t.Errorf("additional-auth not found: %v", decoded.Contexts) + } + if decoded.Contexts[1].Name != "fake-context" { + t.Errorf("fake-context not found: %v", decoded.Contexts) + } + }) + t.Run("configuration_view with minified=false returns cluster info", func(t *testing.T) { + if len(decoded.Clusters) != 2 { + t.Errorf("invalid cluster count, expected 2, got %v", len(decoded.Clusters)) + } + if decoded.Clusters[0].Name != "additional-cluster" { + t.Errorf("additional-cluster not found: %v", decoded.Clusters) + } + }) + t.Run("configuration_view with minified=false returns auth info", func(t *testing.T) { + if len(decoded.AuthInfos) != 2 { + t.Errorf("invalid auth info count, expected 2, got %v", len(decoded.AuthInfos)) + } + if decoded.AuthInfos[0].Name != "additional-auth" { + t.Errorf("additional-auth not found: %v", decoded.AuthInfos) + } + }) + }) +} + +func TestConfigurationViewInCluster(t *testing.T) { + kubernetes.InClusterConfig = func() (*rest.Config, error) { + return &rest.Config{ + Host: "https://kubernetes.default.svc", + BearerToken: "fake-token", + }, nil + } + defer func() { + kubernetes.InClusterConfig = rest.InClusterConfig + }() + testCase(t, func(c *mcpContext) { + toolResult, err := c.callTool("configuration_view", map[string]interface{}{}) + t.Run("configuration_view returns configuration", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + }) + var decoded *v1.Config + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("configuration_view has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("configuration_view returns current-context", func(t *testing.T) { + if decoded.CurrentContext != "context" { + t.Fatalf("context not found: %v", decoded.CurrentContext) + } + }) + t.Run("configuration_view returns context info", func(t *testing.T) { + if len(decoded.Contexts) != 1 { + t.Fatalf("invalid context count, expected 1, got %v", len(decoded.Contexts)) + } + if decoded.Contexts[0].Name != "context" { + t.Fatalf("context not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.Cluster != "cluster" { + t.Fatalf("cluster not found: %v", decoded.Contexts) + } + if decoded.Contexts[0].Context.AuthInfo != "user" { + t.Fatalf("user not found: %v", decoded.Contexts) + } + }) + t.Run("configuration_view returns cluster info", func(t *testing.T) { + if len(decoded.Clusters) != 1 { + t.Fatalf("invalid cluster count, expected 1, got %v", len(decoded.Clusters)) + } + if decoded.Clusters[0].Name != "cluster" { + t.Fatalf("cluster not found: %v", decoded.Clusters) + } + if decoded.Clusters[0].Cluster.Server != "https://kubernetes.default.svc" { + t.Fatalf("server not found: %v", decoded.Clusters) + } + }) + t.Run("configuration_view returns auth info", func(t *testing.T) { + if len(decoded.AuthInfos) != 1 { + t.Fatalf("invalid auth info count, expected 1, got %v", len(decoded.AuthInfos)) + } + if decoded.AuthInfos[0].Name != "user" { + t.Fatalf("user not found: %v", decoded.AuthInfos) + } + }) + }) +} diff --git a/pkg 2/mcp/events.go b/pkg 2/mcp/events.go new file mode 100644 index 00000000..4429a6cd --- /dev/null +++ b/pkg 2/mcp/events.go @@ -0,0 +1,49 @@ +package mcp + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + + "github.com/containers/kubernetes-mcp-server/pkg/output" +) + +func (s *Server) initEvents() []server.ServerTool { + return []server.ServerTool{ + {Tool: mcp.NewTool("events_list", + mcp.WithDescription("List all the Kubernetes events in the current cluster from all namespaces"), + mcp.WithString("namespace", + mcp.Description("Optional Namespace to retrieve the events from. If not provided, will list events from all namespaces")), + // Tool annotations + mcp.WithTitleAnnotation("Events: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.eventsList}, + } +} + +func (s *Server) eventsList(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + namespace := ctr.GetArguments()["namespace"] + if namespace == nil { + namespace = "" + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + eventMap, err := derived.EventsList(ctx, namespace.(string)) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list events in all namespaces: %v", err)), nil + } + if len(eventMap) == 0 { + return NewTextResult("No events found", nil), nil + } + yamlEvents, err := output.MarshalYaml(eventMap) + if err != nil { + err = fmt.Errorf("failed to list events in all namespaces: %v", err) + } + return NewTextResult(fmt.Sprintf("The following events (YAML format) were found:\n%s", yamlEvents), err), nil +} diff --git a/pkg 2/mcp/events_test.go b/pkg 2/mcp/events_test.go new file mode 100644 index 00000000..f6609ed4 --- /dev/null +++ b/pkg 2/mcp/events_test.go @@ -0,0 +1,115 @@ +package mcp + +import ( + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/mark3labs/mcp-go/mcp" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" +) + +func TestEventsList(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + toolResult, err := c.callTool("events_list", map[string]interface{}{}) + t.Run("events_list with no events returns OK", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "No events found" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + client := c.newKubernetesClient() + for _, ns := range []string{"default", "ns-1"} { + _, _ = client.CoreV1().Events(ns).Create(c.ctx, &v1.Event{ + ObjectMeta: metav1.ObjectMeta{ + Name: "an-event-in-" + ns, + }, + InvolvedObject: v1.ObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Name: "a-pod", + Namespace: ns, + }, + Type: "Normal", + Message: "The event message", + }, metav1.CreateOptions{}) + } + toolResult, err = c.callTool("events_list", map[string]interface{}{}) + t.Run("events_list with events returns all OK", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "The following events (YAML format) were found:\n"+ + "- InvolvedObject:\n"+ + " Kind: Pod\n"+ + " Name: a-pod\n"+ + " apiVersion: v1\n"+ + " Message: The event message\n"+ + " Namespace: default\n"+ + " Reason: \"\"\n"+ + " Timestamp: 0001-01-01 00:00:00 +0000 UTC\n"+ + " Type: Normal\n"+ + "- InvolvedObject:\n"+ + " Kind: Pod\n"+ + " Name: a-pod\n"+ + " apiVersion: v1\n"+ + " Message: The event message\n"+ + " Namespace: ns-1\n"+ + " Reason: \"\"\n"+ + " Timestamp: 0001-01-01 00:00:00 +0000 UTC\n"+ + " Type: Normal\n" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + toolResult, err = c.callTool("events_list", map[string]interface{}{ + "namespace": "ns-1", + }) + t.Run("events_list in namespace with events returns from namespace OK", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "The following events (YAML format) were found:\n"+ + "- InvolvedObject:\n"+ + " Kind: Pod\n"+ + " Name: a-pod\n"+ + " apiVersion: v1\n"+ + " Message: The event message\n"+ + " Namespace: ns-1\n"+ + " Reason: \"\"\n"+ + " Timestamp: 0001-01-01 00:00:00 +0000 UTC\n"+ + " Type: Normal\n" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestEventsListDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Event"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + eventList, _ := c.callTool("events_list", map[string]interface{}{}) + t.Run("events_list has error", func(t *testing.T) { + if !eventList.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("events_list describes denial", func(t *testing.T) { + expectedMessage := "failed to list events in all namespaces: resource not allowed: /v1, Kind=Event" + if eventList.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, eventList.Content[0].(mcp.TextContent).Text) + } + }) + }) +} diff --git a/pkg 2/mcp/helm.go b/pkg 2/mcp/helm.go new file mode 100644 index 00000000..e2659653 --- /dev/null +++ b/pkg 2/mcp/helm.go @@ -0,0 +1,118 @@ +package mcp + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" +) + +func (s *Server) initHelm() []server.ServerTool { + return []server.ServerTool{ + {Tool: mcp.NewTool("helm_install", + mcp.WithDescription("Install a Helm chart in the current or provided namespace"), + mcp.WithString("chart", mcp.Description("Chart reference to install (for example: stable/grafana, oci://ghcr.io/nginxinc/charts/nginx-ingress)"), mcp.Required()), + mcp.WithObject("values", mcp.Description("Values to pass to the Helm chart (Optional)")), + mcp.WithString("name", mcp.Description("Name of the Helm release (Optional, random name if not provided)")), + mcp.WithString("namespace", mcp.Description("Namespace to install the Helm chart in (Optional, current namespace if not provided)")), + // Tool annotations + mcp.WithTitleAnnotation("Helm: Install"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithIdempotentHintAnnotation(false), // TODO: consider replacing implementation with equivalent to: helm upgrade --install + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.helmInstall}, + {Tool: mcp.NewTool("helm_list", + mcp.WithDescription("List all the Helm releases in the current or provided namespace (or in all namespaces if specified)"), + mcp.WithString("namespace", mcp.Description("Namespace to list Helm releases from (Optional, all namespaces if not provided)")), + mcp.WithBoolean("all_namespaces", mcp.Description("If true, lists all Helm releases in all namespaces ignoring the namespace argument (Optional)")), + // Tool annotations + mcp.WithTitleAnnotation("Helm: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.helmList}, + {Tool: mcp.NewTool("helm_uninstall", + mcp.WithDescription("Uninstall a Helm release in the current or provided namespace"), + mcp.WithString("name", mcp.Description("Name of the Helm release to uninstall"), mcp.Required()), + mcp.WithString("namespace", mcp.Description("Namespace to uninstall the Helm release from (Optional, current namespace if not provided)")), + // Tool annotations + mcp.WithTitleAnnotation("Helm: Uninstall"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(true), + mcp.WithIdempotentHintAnnotation(true), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.helmUninstall}, + } +} + +func (s *Server) helmInstall(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + var chart string + ok := false + if chart, ok = ctr.GetArguments()["chart"].(string); !ok { + return NewTextResult("", fmt.Errorf("failed to install helm chart, missing argument chart")), nil + } + values := map[string]interface{}{} + if v, ok := ctr.GetArguments()["values"].(map[string]interface{}); ok { + values = v + } + name := "" + if v, ok := ctr.GetArguments()["name"].(string); ok { + name = v + } + namespace := "" + if v, ok := ctr.GetArguments()["namespace"].(string); ok { + namespace = v + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.NewHelm().Install(ctx, chart, values, name, namespace) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to install helm chart '%s': %w", chart, err)), nil + } + return NewTextResult(ret, err), nil +} + +func (s *Server) helmList(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + allNamespaces := false + if v, ok := ctr.GetArguments()["all_namespaces"].(bool); ok { + allNamespaces = v + } + namespace := "" + if v, ok := ctr.GetArguments()["namespace"].(string); ok { + namespace = v + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.NewHelm().List(namespace, allNamespaces) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list helm releases in namespace '%s': %w", namespace, err)), nil + } + return NewTextResult(ret, err), nil +} + +func (s *Server) helmUninstall(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + var name string + ok := false + if name, ok = ctr.GetArguments()["name"].(string); !ok { + return NewTextResult("", fmt.Errorf("failed to uninstall helm chart, missing argument name")), nil + } + namespace := "" + if v, ok := ctr.GetArguments()["namespace"].(string); ok { + namespace = v + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.NewHelm().Uninstall(name, namespace) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to uninstall helm chart '%s': %w", name, err)), nil + } + return NewTextResult(ret, err), nil +} diff --git a/pkg 2/mcp/helm_test.go b/pkg 2/mcp/helm_test.go new file mode 100644 index 00000000..2195b20a --- /dev/null +++ b/pkg 2/mcp/helm_test.go @@ -0,0 +1,264 @@ +package mcp + +import ( + "context" + "encoding/base64" + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/mark3labs/mcp-go/mcp" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "path/filepath" + "runtime" + "sigs.k8s.io/yaml" + "strings" + "testing" +) + +func TestHelmInstall(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + _, file, _, _ := runtime.Caller(0) + chartPath := filepath.Join(filepath.Dir(file), "testdata", "helm-chart-no-op") + toolResult, err := c.callTool("helm_install", map[string]interface{}{ + "chart": chartPath, + }) + t.Run("helm_install with local chart and no release name, returns installed chart", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + var decoded []map[string]interface{} + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + if !strings.HasPrefix(decoded[0]["name"].(string), "helm-chart-no-op-") { + t.Fatalf("invalid helm install name, expected no-op-*, got %v", decoded[0]["name"]) + } + if decoded[0]["namespace"] != "default" { + t.Fatalf("invalid helm install namespace, expected default, got %v", decoded[0]["namespace"]) + } + if decoded[0]["chart"] != "no-op" { + t.Fatalf("invalid helm install name, expected release name, got empty") + } + if decoded[0]["chartVersion"] != "1.33.7" { + t.Fatalf("invalid helm install version, expected 1.33.7, got empty") + } + if decoded[0]["status"] != "deployed" { + t.Fatalf("invalid helm install status, expected deployed, got %v", decoded[0]["status"]) + } + if decoded[0]["revision"] != float64(1) { + t.Fatalf("invalid helm install revision, expected 1, got %v", decoded[0]["revision"]) + } + }) + }) +} + +func TestHelmInstallDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Secret"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + _, file, _, _ := runtime.Caller(0) + chartPath := filepath.Join(filepath.Dir(file), "testdata", "helm-chart-secret") + helmInstall, _ := c.callTool("helm_install", map[string]interface{}{ + "chart": chartPath, + }) + t.Run("helm_install has error", func(t *testing.T) { + if !helmInstall.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("helm_install describes denial", func(t *testing.T) { + toolOutput := helmInstall.Content[0].(mcp.TextContent).Text + expectedMessage := ": resource not allowed: /v1, Kind=Secret" + if !strings.HasPrefix(toolOutput, "failed to install helm chart") || !strings.HasSuffix(toolOutput, expectedMessage) { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, helmInstall.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestHelmList(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + clearHelmReleases(c.ctx, kc) + toolResult, err := c.callTool("helm_list", map[string]interface{}{}) + t.Run("helm_list with no releases, returns not found", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "No Helm releases found" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + _, _ = kc.CoreV1().Secrets("default").Create(c.ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.release-to-list", + Labels: map[string]string{"owner": "helm", "name": "release-to-list"}, + }, + Data: map[string][]byte{ + "release": []byte(base64.StdEncoding.EncodeToString([]byte("{" + + "\"name\":\"release-to-list\"," + + "\"info\":{\"status\":\"deployed\"}" + + "}"))), + }, + }, metav1.CreateOptions{}) + toolResult, err = c.callTool("helm_list", map[string]interface{}{}) + t.Run("helm_list with deployed release, returns release", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + var decoded []map[string]interface{} + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + if len(decoded) != 1 { + t.Fatalf("invalid helm list count, expected 1, got %v", len(decoded)) + } + if decoded[0]["name"] != "release-to-list" { + t.Fatalf("invalid helm list name, expected release-to-list, got %v", decoded[0]["name"]) + } + if decoded[0]["status"] != "deployed" { + t.Fatalf("invalid helm list status, expected deployed, got %v", decoded[0]["status"]) + } + }) + toolResult, err = c.callTool("helm_list", map[string]interface{}{"namespace": "ns-1"}) + t.Run("helm_list with deployed release in other namespaces, returns not found", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "No Helm releases found" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + toolResult, err = c.callTool("helm_list", map[string]interface{}{"namespace": "ns-1", "all_namespaces": true}) + t.Run("helm_list with deployed release in all namespaces, returns release", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + var decoded []map[string]interface{} + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + if len(decoded) != 1 { + t.Fatalf("invalid helm list count, expected 1, got %v", len(decoded)) + } + if decoded[0]["name"] != "release-to-list" { + t.Fatalf("invalid helm list name, expected release-to-list, got %v", decoded[0]["name"]) + } + if decoded[0]["status"] != "deployed" { + t.Fatalf("invalid helm list status, expected deployed, got %v", decoded[0]["status"]) + } + }) + }) +} + +func TestHelmUninstall(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + clearHelmReleases(c.ctx, kc) + toolResult, err := c.callTool("helm_uninstall", map[string]interface{}{ + "name": "release-to-uninstall", + }) + t.Run("helm_uninstall with no releases, returns not found", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if toolResult.Content[0].(mcp.TextContent).Text != "Release release-to-uninstall not found" { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + _, _ = kc.CoreV1().Secrets("default").Create(c.ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.existent-release-to-uninstall.v0", + Labels: map[string]string{"owner": "helm", "name": "existent-release-to-uninstall"}, + }, + Data: map[string][]byte{ + "release": []byte(base64.StdEncoding.EncodeToString([]byte("{" + + "\"name\":\"existent-release-to-uninstall\"," + + "\"info\":{\"status\":\"deployed\"}" + + "}"))), + }, + }, metav1.CreateOptions{}) + toolResult, err = c.callTool("helm_uninstall", map[string]interface{}{ + "name": "existent-release-to-uninstall", + }) + t.Run("helm_uninstall with deployed release, returns uninstalled", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + if !strings.HasPrefix(toolResult.Content[0].(mcp.TextContent).Text, "Uninstalled release existent-release-to-uninstall") { + t.Fatalf("unexpected result %v", toolResult.Content[0].(mcp.TextContent).Text) + } + _, err = kc.CoreV1().Secrets("default").Get(c.ctx, "sh.helm.release.v1.existent-release-to-uninstall.v0", metav1.GetOptions{}) + if !errors.IsNotFound(err) { + t.Fatalf("expected release to be deleted, but it still exists") + } + }) + }) +} + +func TestHelmUninstallDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Secret"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + clearHelmReleases(c.ctx, kc) + _, _ = kc.CoreV1().Secrets("default").Create(c.ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sh.helm.release.v1.existent-release-to-uninstall.v0", + Labels: map[string]string{"owner": "helm", "name": "existent-release-to-uninstall"}, + }, + Data: map[string][]byte{ + "release": []byte(base64.StdEncoding.EncodeToString([]byte("{" + + "\"name\":\"existent-release-to-uninstall\"," + + "\"info\":{\"status\":\"deployed\"}," + + "\"manifest\":\"apiVersion: v1\\nkind: Secret\\nmetadata:\\n name: secret-to-deny\\n namespace: default\\n\"" + + "}"))), + }, + }, metav1.CreateOptions{}) + helmUninstall, _ := c.callTool("helm_uninstall", map[string]interface{}{ + "name": "existent-release-to-uninstall", + }) + t.Run("helm_uninstall has error", func(t *testing.T) { + if !helmUninstall.IsError { + t.Fatalf("call tool should fail") + } + }) + }) +} + +func clearHelmReleases(ctx context.Context, kc *kubernetes.Clientset) { + secrets, _ := kc.CoreV1().Secrets("default").List(ctx, metav1.ListOptions{}) + for _, secret := range secrets.Items { + if strings.HasPrefix(secret.Name, "sh.helm.release.v1.") { + _ = kc.CoreV1().Secrets("default").Delete(ctx, secret.Name, metav1.DeleteOptions{}) + } + } +} diff --git a/pkg 2/mcp/mcp.go b/pkg 2/mcp/mcp.go new file mode 100644 index 00000000..cf7676a3 --- /dev/null +++ b/pkg 2/mcp/mcp.go @@ -0,0 +1,212 @@ +package mcp + +import ( + "bytes" + "context" + "fmt" + "k8s.io/klog/v2" + "net/http" + "slices" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + authenticationapiv1 "k8s.io/api/authentication/v1" + "k8s.io/utils/ptr" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + internalk8s "github.com/containers/kubernetes-mcp-server/pkg/kubernetes" + "github.com/containers/kubernetes-mcp-server/pkg/output" + "github.com/containers/kubernetes-mcp-server/pkg/version" +) + +const TokenScopesContextKey = "TokenScopesContextKey" + +type Configuration struct { + Profile Profile + ListOutput output.Output + + StaticConfig *config.StaticConfig +} + +func (c *Configuration) isToolApplicable(tool server.ServerTool) bool { + if c.StaticConfig.ReadOnly && !ptr.Deref(tool.Tool.Annotations.ReadOnlyHint, false) { + return false + } + if c.StaticConfig.DisableDestructive && ptr.Deref(tool.Tool.Annotations.DestructiveHint, false) { + return false + } + if c.StaticConfig.EnabledTools != nil && !slices.Contains(c.StaticConfig.EnabledTools, tool.Tool.Name) { + return false + } + if c.StaticConfig.DisabledTools != nil && slices.Contains(c.StaticConfig.DisabledTools, tool.Tool.Name) { + return false + } + return true +} + +type Server struct { + configuration *Configuration + server *server.MCPServer + enabledTools []string + k *internalk8s.Manager +} + +func NewServer(configuration Configuration) (*Server, error) { + var serverOptions []server.ServerOption + serverOptions = append(serverOptions, + server.WithResourceCapabilities(true, true), + server.WithPromptCapabilities(true), + server.WithToolCapabilities(true), + server.WithLogging(), + server.WithToolHandlerMiddleware(toolCallLoggingMiddleware), + ) + if configuration.StaticConfig.RequireOAuth { + serverOptions = append(serverOptions, server.WithToolHandlerMiddleware(toolScopedAuthorizationMiddleware)) + } + + s := &Server{ + configuration: &configuration, + server: server.NewMCPServer( + version.BinaryName, + version.Version, + serverOptions..., + ), + } + if err := s.reloadKubernetesClient(); err != nil { + return nil, err + } + s.k.WatchKubeConfig(s.reloadKubernetesClient) + + return s, nil +} + +func (s *Server) reloadKubernetesClient() error { + k, err := internalk8s.NewManager(s.configuration.StaticConfig) + if err != nil { + return err + } + s.k = k + applicableTools := make([]server.ServerTool, 0) + for _, tool := range s.configuration.Profile.GetTools(s) { + if !s.configuration.isToolApplicable(tool) { + continue + } + applicableTools = append(applicableTools, tool) + s.enabledTools = append(s.enabledTools, tool.Tool.Name) + } + s.server.SetTools(applicableTools...) + return nil +} + +func (s *Server) ServeStdio() error { + return server.ServeStdio(s.server) +} + +func (s *Server) ServeSse(baseUrl string, httpServer *http.Server) *server.SSEServer { + options := make([]server.SSEOption, 0) + options = append(options, server.WithSSEContextFunc(contextFunc), server.WithHTTPServer(httpServer)) + if baseUrl != "" { + options = append(options, server.WithBaseURL(baseUrl)) + } + return server.NewSSEServer(s.server, options...) +} + +func (s *Server) ServeHTTP(httpServer *http.Server) *server.StreamableHTTPServer { + options := []server.StreamableHTTPOption{ + server.WithHTTPContextFunc(contextFunc), + server.WithStreamableHTTPServer(httpServer), + server.WithStateLess(true), + } + return server.NewStreamableHTTPServer(s.server, options...) +} + +// VerifyTokenAPIServer verifies the given token with the audience by +// sending an TokenReview request to API Server. +func (s *Server) VerifyTokenAPIServer(ctx context.Context, token string, audience string) (*authenticationapiv1.UserInfo, []string, error) { + if s.k == nil { + return nil, nil, fmt.Errorf("kubernetes manager is not initialized") + } + return s.k.VerifyToken(ctx, token, audience) +} + +// GetKubernetesAPIServerHost returns the Kubernetes API server host from the configuration. +func (s *Server) GetKubernetesAPIServerHost() string { + if s.k == nil { + return "" + } + return s.k.GetAPIServerHost() +} + +func (s *Server) GetEnabledTools() []string { + return s.enabledTools +} + +func (s *Server) Close() { + if s.k != nil { + s.k.Close() + } +} + +func NewTextResult(content string, err error) *mcp.CallToolResult { + if err != nil { + return &mcp.CallToolResult{ + IsError: true, + Content: []mcp.Content{ + mcp.TextContent{ + Type: "text", + Text: err.Error(), + }, + }, + } + } + return &mcp.CallToolResult{ + Content: []mcp.Content{ + mcp.TextContent{ + Type: "text", + Text: content, + }, + }, + } +} + +func contextFunc(ctx context.Context, r *http.Request) context.Context { + // Get the standard Authorization header (OAuth compliant) + authHeader := r.Header.Get(string(internalk8s.OAuthAuthorizationHeader)) + if authHeader != "" { + return context.WithValue(ctx, internalk8s.OAuthAuthorizationHeader, authHeader) + } + + // Fallback to custom header for backward compatibility + customAuthHeader := r.Header.Get(string(internalk8s.CustomAuthorizationHeader)) + if customAuthHeader != "" { + return context.WithValue(ctx, internalk8s.OAuthAuthorizationHeader, customAuthHeader) + } + + return ctx +} + +func toolCallLoggingMiddleware(next server.ToolHandlerFunc) server.ToolHandlerFunc { + return func(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + klog.V(5).Infof("mcp tool call: %s(%v)", ctr.Params.Name, ctr.Params.Arguments) + if ctr.Header != nil { + buffer := bytes.NewBuffer(make([]byte, 0)) + if err := ctr.Header.WriteSubset(buffer, map[string]bool{"Authorization": true, "authorization": true}); err == nil { + klog.V(7).Infof("mcp tool call headers: %s", buffer) + } + } + return next(ctx, ctr) + } +} + +func toolScopedAuthorizationMiddleware(next server.ToolHandlerFunc) server.ToolHandlerFunc { + return func(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + scopes, ok := ctx.Value(TokenScopesContextKey).([]string) + if !ok { + return NewTextResult("", fmt.Errorf("Authorization failed: Access denied: Tool '%s' requires scope 'mcp:%s' but no scope is available", ctr.Params.Name, ctr.Params.Name)), nil + } + if !slices.Contains(scopes, "mcp:"+ctr.Params.Name) && !slices.Contains(scopes, ctr.Params.Name) { + return NewTextResult("", fmt.Errorf("Authorization failed: Access denied: Tool '%s' requires scope 'mcp:%s' but only scopes %s are available", ctr.Params.Name, ctr.Params.Name, scopes)), nil + } + return next(ctx, ctr) + } +} diff --git a/pkg 2/mcp/mcp_test.go b/pkg 2/mcp/mcp_test.go new file mode 100644 index 00000000..9b2c78ef --- /dev/null +++ b/pkg 2/mcp/mcp_test.go @@ -0,0 +1,126 @@ +package mcp + +import ( + "context" + "net/http" + "os" + "path/filepath" + "runtime" + "testing" + "time" + + "github.com/mark3labs/mcp-go/client" + "github.com/mark3labs/mcp-go/mcp" +) + +func TestWatchKubeConfig(t *testing.T) { + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { + t.Skip("Skipping test on non-Unix-like platforms") + } + testCase(t, func(c *mcpContext) { + // Given + withTimeout, cancel := context.WithTimeout(c.ctx, 5*time.Second) + defer cancel() + var notification *mcp.JSONRPCNotification + c.mcpClient.OnNotification(func(n mcp.JSONRPCNotification) { + notification = &n + }) + // When + f, _ := os.OpenFile(filepath.Join(c.tempDir, "config"), os.O_APPEND|os.O_WRONLY, 0644) + _, _ = f.WriteString("\n") + for notification == nil { + select { + case <-withTimeout.Done(): + default: + time.Sleep(100 * time.Millisecond) + } + } + // Then + t.Run("WatchKubeConfig notifies tools change", func(t *testing.T) { + if notification == nil { + t.Fatalf("WatchKubeConfig did not notify") + } + if notification.Method != "notifications/tools/list_changed" { + t.Fatalf("WatchKubeConfig did not notify tools change, got %s", notification.Method) + } + }) + }) +} + +func TestSseHeaders(t *testing.T) { + mockServer := NewMockServer() + defer mockServer.Close() + before := func(c *mcpContext) { + c.withKubeConfig(mockServer.config) + c.clientOptions = append(c.clientOptions, client.WithHeaders(map[string]string{"kubernetes-authorization": "Bearer a-token-from-mcp-client"})) + } + pathHeaders := make(map[string]http.Header, 0) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + pathHeaders[req.URL.Path] = req.Header.Clone() + // Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-) + if req.URL.Path == "/api" { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"kind":"APIVersions","versions":["v1"],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Groups) + if req.URL.Path == "/apis" { + w.Header().Set("Content-Type", "application/json") + //w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[{"name":"apps","versions":[{"groupVersion":"apps/v1","version":"v1"}],"preferredVersion":{"groupVersion":"apps/v1","version":"v1"}}]}`)) + _, _ = w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Resources) + if req.URL.Path == "/api/v1" { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"kind":"APIResourceList","apiVersion":"v1","resources":[{"name":"pods","singularName":"","namespaced":true,"kind":"Pod","verbs":["get","list","watch","create","update","patch","delete"]}]}`)) + return + } + // Request Performed by DynamicClient + if req.URL.Path == "/api/v1/namespaces/default/pods" { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"kind":"PodList","apiVersion":"v1","items":[]}`)) + return + } + // Request Performed by kubernetes.Interface + if req.URL.Path == "/api/v1/namespaces/default/pods/a-pod-to-delete" { + w.WriteHeader(200) + return + } + w.WriteHeader(404) + })) + testCaseWithContext(t, &mcpContext{before: before}, func(c *mcpContext) { + _, _ = c.callTool("pods_list", map[string]interface{}{}) + t.Run("DiscoveryClient propagates headers to Kube API", func(t *testing.T) { + if len(pathHeaders) == 0 { + t.Fatalf("No requests were made to Kube API") + } + if pathHeaders["/api"] == nil || pathHeaders["/api"].Get("Authorization") != "Bearer a-token-from-mcp-client" { + t.Fatalf("Overridden header Authorization not found in request to /api") + } + if pathHeaders["/apis"] == nil || pathHeaders["/apis"].Get("Authorization") != "Bearer a-token-from-mcp-client" { + t.Fatalf("Overridden header Authorization not found in request to /apis") + } + if pathHeaders["/api/v1"] == nil || pathHeaders["/api/v1"].Get("Authorization") != "Bearer a-token-from-mcp-client" { + t.Fatalf("Overridden header Authorization not found in request to /api/v1") + } + }) + t.Run("DynamicClient propagates headers to Kube API", func(t *testing.T) { + if len(pathHeaders) == 0 { + t.Fatalf("No requests were made to Kube API") + } + if pathHeaders["/api/v1/namespaces/default/pods"] == nil || pathHeaders["/api/v1/namespaces/default/pods"].Get("Authorization") != "Bearer a-token-from-mcp-client" { + t.Fatalf("Overridden header Authorization not found in request to /api/v1/namespaces/default/pods") + } + }) + _, _ = c.callTool("pods_delete", map[string]interface{}{"name": "a-pod-to-delete"}) + t.Run("kubernetes.Interface propagates headers to Kube API", func(t *testing.T) { + if len(pathHeaders) == 0 { + t.Fatalf("No requests were made to Kube API") + } + if pathHeaders["/api/v1/namespaces/default/pods/a-pod-to-delete"] == nil || pathHeaders["/api/v1/namespaces/default/pods/a-pod-to-delete"].Get("Authorization") != "Bearer a-token-from-mcp-client" { + t.Fatalf("Overridden header Authorization not found in request to /api/v1/namespaces/default/pods/a-pod-to-delete") + } + }) + }) +} diff --git a/pkg 2/mcp/mcp_tools_test.go b/pkg 2/mcp/mcp_tools_test.go new file mode 100644 index 00000000..4d12d306 --- /dev/null +++ b/pkg 2/mcp/mcp_tools_test.go @@ -0,0 +1,179 @@ +package mcp + +import ( + "github.com/mark3labs/mcp-go/client/transport" + "github.com/mark3labs/mcp-go/mcp" + "k8s.io/utils/ptr" + "regexp" + "strings" + "testing" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +func TestUnrestricted(t *testing.T) { + testCase(t, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("Destructive tools ARE NOT read only", func(t *testing.T) { + for _, tool := range tools.Tools { + readOnly := ptr.Deref(tool.Annotations.ReadOnlyHint, false) + destructive := ptr.Deref(tool.Annotations.DestructiveHint, false) + if readOnly && destructive { + t.Errorf("Tool %s is read-only and destructive, which is not allowed", tool.Name) + } + } + }) + }) +} + +func TestReadOnly(t *testing.T) { + readOnlyServer := func(c *mcpContext) { c.staticConfig = &config.StaticConfig{ReadOnly: true} } + testCaseWithContext(t, &mcpContext{before: readOnlyServer}, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("ListTools returns only read-only tools", func(t *testing.T) { + for _, tool := range tools.Tools { + if tool.Annotations.ReadOnlyHint == nil || !*tool.Annotations.ReadOnlyHint { + t.Errorf("Tool %s is not read-only but should be", tool.Name) + } + if tool.Annotations.DestructiveHint != nil && *tool.Annotations.DestructiveHint { + t.Errorf("Tool %s is destructive but should not be in read-only mode", tool.Name) + } + } + }) + }) +} + +func TestDisableDestructive(t *testing.T) { + disableDestructiveServer := func(c *mcpContext) { c.staticConfig = &config.StaticConfig{DisableDestructive: true} } + testCaseWithContext(t, &mcpContext{before: disableDestructiveServer}, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("ListTools does not return destructive tools", func(t *testing.T) { + for _, tool := range tools.Tools { + if tool.Annotations.DestructiveHint != nil && *tool.Annotations.DestructiveHint { + t.Errorf("Tool %s is destructive but should not be", tool.Name) + } + } + }) + }) +} + +func TestEnabledTools(t *testing.T) { + testCaseWithContext(t, &mcpContext{ + staticConfig: &config.StaticConfig{ + EnabledTools: []string{"namespaces_list", "events_list"}, + }, + }, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("ListTools returns only explicitly enabled tools", func(t *testing.T) { + if len(tools.Tools) != 2 { + t.Fatalf("ListTools should return 2 tools, got %d", len(tools.Tools)) + } + for _, tool := range tools.Tools { + if tool.Name != "namespaces_list" && tool.Name != "events_list" { + t.Errorf("Tool %s is not enabled but should be", tool.Name) + } + } + }) + }) +} + +func TestDisabledTools(t *testing.T) { + testCaseWithContext(t, &mcpContext{ + staticConfig: &config.StaticConfig{ + DisabledTools: []string{"namespaces_list", "events_list"}, + }, + }, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("ListTools does not return disabled tools", func(t *testing.T) { + for _, tool := range tools.Tools { + if tool.Name == "namespaces_list" || tool.Name == "events_list" { + t.Errorf("Tool %s is not disabled but should be", tool.Name) + } + } + }) + }) +} + +func TestToolCallLogging(t *testing.T) { + testCaseWithContext(t, &mcpContext{logLevel: 5}, func(c *mcpContext) { + _, _ = c.callTool("configuration_view", map[string]interface{}{ + "minified": false, + }) + t.Run("Logs tool name", func(t *testing.T) { + expectedLog := "mcp tool call: configuration_view(" + if !strings.Contains(c.logBuffer.String(), expectedLog) { + t.Errorf("Expected log to contain '%s', got: %s", expectedLog, c.logBuffer.String()) + } + }) + t.Run("Logs tool call arguments", func(t *testing.T) { + expected := `"mcp tool call: configuration_view\((.+)\)"` + m := regexp.MustCompile(expected).FindStringSubmatch(c.logBuffer.String()) + if len(m) != 2 { + t.Fatalf("Expected log entry to contain arguments, got %s", c.logBuffer.String()) + } + if m[1] != "map[minified:false]" { + t.Errorf("Expected log arguments to be 'map[minified:false]', got %s", m[1]) + } + }) + }) + before := func(c *mcpContext) { + c.clientOptions = append(c.clientOptions, transport.WithHeaders(map[string]string{ + "Accept-Encoding": "gzip", + "Authorization": "Bearer should-not-be-logged", + "authorization": "Bearer should-not-be-logged", + "a-loggable-header": "should-be-logged", + })) + } + testCaseWithContext(t, &mcpContext{logLevel: 7, before: before}, func(c *mcpContext) { + _, _ = c.callTool("configuration_view", map[string]interface{}{ + "minified": false, + }) + t.Run("Logs tool call headers", func(t *testing.T) { + expectedLog := "mcp tool call headers: A-Loggable-Header: should-be-logged" + if !strings.Contains(c.logBuffer.String(), expectedLog) { + t.Errorf("Expected log to contain '%s', got: %s", expectedLog, c.logBuffer.String()) + } + }) + sensitiveHeaders := []string{ + "Authorization", + // TODO: Add more sensitive headers as needed + } + t.Run("Does not log sensitive headers", func(t *testing.T) { + for _, header := range sensitiveHeaders { + if strings.Contains(c.logBuffer.String(), header) { + t.Errorf("Log should not contain sensitive header '%s', got: %s", header, c.logBuffer.String()) + } + } + }) + t.Run("Does not log sensitive header values", func(t *testing.T) { + if strings.Contains(c.logBuffer.String(), "should-not-be-logged") { + t.Errorf("Log should not contain sensitive header value 'should-not-be-logged', got: %s", c.logBuffer.String()) + } + }) + }) +} diff --git a/pkg 2/mcp/mock_server_test.go b/pkg 2/mcp/mock_server_test.go new file mode 100644 index 00000000..124e5ab5 --- /dev/null +++ b/pkg 2/mcp/mock_server_test.go @@ -0,0 +1,151 @@ +package mcp + +import ( + "encoding/json" + "errors" + "io" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/httpstream/spdy" + "k8s.io/client-go/rest" + "net/http" + "net/http/httptest" +) + +type MockServer struct { + server *httptest.Server + config *rest.Config + restHandlers []http.HandlerFunc +} + +func NewMockServer() *MockServer { + ms := &MockServer{} + scheme := runtime.NewScheme() + codecs := serializer.NewCodecFactory(scheme) + ms.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + for _, handler := range ms.restHandlers { + handler(w, req) + } + })) + ms.config = &rest.Config{ + Host: ms.server.URL, + APIPath: "/api", + ContentConfig: rest.ContentConfig{ + NegotiatedSerializer: codecs, + ContentType: runtime.ContentTypeJSON, + GroupVersion: &v1.SchemeGroupVersion, + }, + } + ms.restHandlers = make([]http.HandlerFunc, 0) + return ms +} + +func (m *MockServer) Close() { + m.server.Close() +} + +func (m *MockServer) Handle(handler http.Handler) { + m.restHandlers = append(m.restHandlers, handler.ServeHTTP) +} + +func writeObject(w http.ResponseWriter, obj runtime.Object) { + w.Header().Set("Content-Type", runtime.ContentTypeJSON) + if err := json.NewEncoder(w).Encode(obj); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +type streamAndReply struct { + httpstream.Stream + replySent <-chan struct{} +} + +type streamContext struct { + conn io.Closer + stdinStream io.ReadCloser + stdoutStream io.WriteCloser + stderrStream io.WriteCloser + writeStatus func(status *apierrors.StatusError) error +} + +type StreamOptions struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +func v4WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error { + return func(status *apierrors.StatusError) error { + bs, err := json.Marshal(status.Status()) + if err != nil { + return err + } + _, err = stream.Write(bs) + return err + } +} +func createHTTPStreams(w http.ResponseWriter, req *http.Request, opts *StreamOptions) (*streamContext, error) { + _, err := httpstream.Handshake(req, w, []string{"v4.channel.k8s.io"}) + if err != nil { + return nil, err + } + + upgrader := spdy.NewResponseUpgrader() + streamCh := make(chan streamAndReply) + conn := upgrader.UpgradeResponse(w, req, func(stream httpstream.Stream, replySent <-chan struct{}) error { + streamCh <- streamAndReply{Stream: stream, replySent: replySent} + return nil + }) + ctx := &streamContext{ + conn: conn, + } + + // wait for stream + replyChan := make(chan struct{}, 4) + defer close(replyChan) + receivedStreams := 0 + expectedStreams := 1 + if opts.Stdout != nil { + expectedStreams++ + } + if opts.Stdin != nil { + expectedStreams++ + } + if opts.Stderr != nil { + expectedStreams++ + } +WaitForStreams: + for { + select { + case stream := <-streamCh: + streamType := stream.Headers().Get(v1.StreamType) + switch streamType { + case v1.StreamTypeError: + replyChan <- struct{}{} + ctx.writeStatus = v4WriteStatusFunc(stream) + case v1.StreamTypeStdout: + replyChan <- struct{}{} + ctx.stdoutStream = stream + case v1.StreamTypeStdin: + replyChan <- struct{}{} + ctx.stdinStream = stream + case v1.StreamTypeStderr: + replyChan <- struct{}{} + ctx.stderrStream = stream + default: + // add other stream ... + return nil, errors.New("unimplemented stream type") + } + case <-replyChan: + receivedStreams++ + if receivedStreams == expectedStreams { + break WaitForStreams + } + } + } + + return ctx, nil +} diff --git a/pkg 2/mcp/namespaces.go b/pkg 2/mcp/namespaces.go new file mode 100644 index 00000000..a2890156 --- /dev/null +++ b/pkg 2/mcp/namespaces.go @@ -0,0 +1,62 @@ +package mcp + +import ( + "context" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + + "github.com/containers/kubernetes-mcp-server/pkg/kubernetes" +) + +func (s *Server) initNamespaces() []server.ServerTool { + ret := make([]server.ServerTool, 0) + ret = append(ret, server.ServerTool{ + Tool: mcp.NewTool("namespaces_list", + mcp.WithDescription("List all the Kubernetes namespaces in the current cluster"), + // Tool annotations + mcp.WithTitleAnnotation("Namespaces: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.namespacesList, + }) + if s.k.IsOpenShift(context.Background()) { + ret = append(ret, server.ServerTool{ + Tool: mcp.NewTool("projects_list", + mcp.WithDescription("List all the OpenShift projects in the current cluster"), + // Tool annotations + mcp.WithTitleAnnotation("Projects: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.projectsList, + }) + } + return ret +} + +func (s *Server) namespacesList(ctx context.Context, _ mcp.CallToolRequest) (*mcp.CallToolResult, error) { + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.NamespacesList(ctx, kubernetes.ResourceListOptions{AsTable: s.configuration.ListOutput.AsTable()}) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list namespaces: %v", err)), nil + } + return NewTextResult(s.configuration.ListOutput.PrintObj(ret)), nil +} + +func (s *Server) projectsList(ctx context.Context, _ mcp.CallToolRequest) (*mcp.CallToolResult, error) { + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.ProjectsList(ctx, kubernetes.ResourceListOptions{AsTable: s.configuration.ListOutput.AsTable()}) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list projects: %v", err)), nil + } + return NewTextResult(s.configuration.ListOutput.PrintObj(ret)), nil +} diff --git a/pkg 2/mcp/namespaces_test.go b/pkg 2/mcp/namespaces_test.go new file mode 100644 index 00000000..c3d5a41c --- /dev/null +++ b/pkg 2/mcp/namespaces_test.go @@ -0,0 +1,174 @@ +package mcp + +import ( + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/output" + "github.com/mark3labs/mcp-go/mcp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "regexp" + "sigs.k8s.io/yaml" + "slices" + "testing" +) + +func TestNamespacesList(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + toolResult, err := c.callTool("namespaces_list", map[string]interface{}{}) + t.Run("namespaces_list returns namespace list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + }) + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("namespaces_list has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("namespaces_list returns at least 3 items", func(t *testing.T) { + if len(decoded) < 3 { + t.Errorf("invalid namespace count, expected at least 3, got %v", len(decoded)) + } + for _, expectedNamespace := range []string{"default", "ns-1", "ns-2"} { + idx := slices.IndexFunc(decoded, func(ns unstructured.Unstructured) bool { + return ns.GetName() == expectedNamespace + }) + if idx == -1 { + t.Errorf("namespace %s not found in the list", expectedNamespace) + } + } + }) + }) +} + +func TestNamespacesListDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Namespace"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + namespacesList, _ := c.callTool("namespaces_list", map[string]interface{}{}) + t.Run("namespaces_list has error", func(t *testing.T) { + if !namespacesList.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("namespaces_list describes denial", func(t *testing.T) { + expectedMessage := "failed to list namespaces: resource not allowed: /v1, Kind=Namespace" + if namespacesList.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, namespacesList.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestNamespacesListAsTable(t *testing.T) { + testCaseWithContext(t, &mcpContext{listOutput: output.Table}, func(c *mcpContext) { + c.withEnvTest() + toolResult, err := c.callTool("namespaces_list", map[string]interface{}{}) + t.Run("namespaces_list returns namespace list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + }) + out := toolResult.Content[0].(mcp.TextContent).Text + t.Run("namespaces_list returns column headers", func(t *testing.T) { + expectedHeaders := "APIVERSION\\s+KIND\\s+NAME\\s+STATUS\\s+AGE\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, out); !m || e != nil { + t.Fatalf("Expected headers '%s' not found in output:\n%s", expectedHeaders, out) + } + }) + t.Run("namespaces_list returns formatted row for ns-1", func(t *testing.T) { + expectedRow := "(?v1)\\s+" + + "(?Namespace)\\s+" + + "(?ns-1)\\s+" + + "(?Active)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?kubernetes.io/metadata.name=ns-1)" + if m, e := regexp.MatchString(expectedRow, out); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, out) + } + }) + t.Run("namespaces_list returns formatted row for ns-2", func(t *testing.T) { + expectedRow := "(?v1)\\s+" + + "(?Namespace)\\s+" + + "(?ns-2)\\s+" + + "(?Active)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?kubernetes.io/metadata.name=ns-2)" + if m, e := regexp.MatchString(expectedRow, out); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, out) + } + }) + }) + +} + +func TestProjectsListInOpenShift(t *testing.T) { + testCaseWithContext(t, &mcpContext{before: inOpenShift, after: inOpenShiftClear}, func(c *mcpContext) { + dynamicClient := dynamic.NewForConfigOrDie(envTestRestConfig) + _, _ = dynamicClient.Resource(schema.GroupVersionResource{Group: "project.openshift.io", Version: "v1", Resource: "projects"}). + Create(c.ctx, &unstructured.Unstructured{Object: map[string]interface{}{ + "apiVersion": "project.openshift.io/v1", + "kind": "Project", + "metadata": map[string]interface{}{ + "name": "an-openshift-project", + }, + }}, metav1.CreateOptions{}) + toolResult, err := c.callTool("projects_list", map[string]interface{}{}) + t.Run("projects_list returns project list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + }) + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("projects_list has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("projects_list returns at least 1 items", func(t *testing.T) { + if len(decoded) < 1 { + t.Errorf("invalid project count, expected at least 1, got %v", len(decoded)) + } + idx := slices.IndexFunc(decoded, func(ns unstructured.Unstructured) bool { + return ns.GetName() == "an-openshift-project" + }) + if idx == -1 { + t.Errorf("namespace %s not found in the list", "an-openshift-project") + } + }) + }) +} + +func TestProjectsListInOpenShiftDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Group: "project.openshift.io", Version: "v1"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer, before: inOpenShift, after: inOpenShiftClear}, func(c *mcpContext) { + c.withEnvTest() + projectsList, _ := c.callTool("projects_list", map[string]interface{}{}) + t.Run("projects_list has error", func(t *testing.T) { + if !projectsList.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("projects_list describes denial", func(t *testing.T) { + expectedMessage := "failed to list projects: resource not allowed: project.openshift.io/v1, Kind=Project" + if projectsList.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, projectsList.Content[0].(mcp.TextContent).Text) + } + }) + }) +} diff --git a/pkg 2/mcp/pods.go b/pkg 2/mcp/pods.go new file mode 100644 index 00000000..0150031d --- /dev/null +++ b/pkg 2/mcp/pods.go @@ -0,0 +1,330 @@ +package mcp + +import ( + "bytes" + "context" + "errors" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + "k8s.io/kubectl/pkg/metricsutil" + + "github.com/containers/kubernetes-mcp-server/pkg/kubernetes" + "github.com/containers/kubernetes-mcp-server/pkg/output" +) + +func (s *Server) initPods() []server.ServerTool { + return []server.ServerTool{ + {Tool: mcp.NewTool("pods_list", + mcp.WithDescription("List all the Kubernetes pods in the current cluster from all namespaces"), + mcp.WithString("labelSelector", mcp.Description("Optional Kubernetes label selector (e.g. 'app=myapp,env=prod' or 'app in (myapp,yourapp)'), use this option when you want to filter the pods by label"), mcp.Pattern("([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsListInAllNamespaces}, + {Tool: mcp.NewTool("pods_list_in_namespace", + mcp.WithDescription("List all the Kubernetes pods in the specified namespace in the current cluster"), + mcp.WithString("namespace", mcp.Description("Namespace to list pods from"), mcp.Required()), + mcp.WithString("labelSelector", mcp.Description("Optional Kubernetes label selector (e.g. 'app=myapp,env=prod' or 'app in (myapp,yourapp)'), use this option when you want to filter the pods by label"), mcp.Pattern("([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: List in Namespace"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsListInNamespace}, + {Tool: mcp.NewTool("pods_get", + mcp.WithDescription("Get a Kubernetes Pod in the current or provided namespace with the provided name"), + mcp.WithString("namespace", mcp.Description("Namespace to get the Pod from")), + mcp.WithString("name", mcp.Description("Name of the Pod"), mcp.Required()), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Get"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsGet}, + {Tool: mcp.NewTool("pods_delete", + mcp.WithDescription("Delete a Kubernetes Pod in the current or provided namespace with the provided name"), + mcp.WithString("namespace", mcp.Description("Namespace to delete the Pod from")), + mcp.WithString("name", mcp.Description("Name of the Pod to delete"), mcp.Required()), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Delete"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(true), + mcp.WithIdempotentHintAnnotation(true), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsDelete}, + {Tool: mcp.NewTool("pods_top", + mcp.WithDescription("List the resource consumption (CPU and memory) as recorded by the Kubernetes Metrics Server for the specified Kubernetes Pods in the all namespaces, the provided namespace, or the current namespace"), + mcp.WithBoolean("all_namespaces", mcp.Description("If true, list the resource consumption for all Pods in all namespaces. If false, list the resource consumption for Pods in the provided namespace or the current namespace"), mcp.DefaultBool(true)), + mcp.WithString("namespace", mcp.Description("Namespace to get the Pods resource consumption from (Optional, current namespace if not provided and all_namespaces is false)")), + mcp.WithString("name", mcp.Description("Name of the Pod to get the resource consumption from (Optional, all Pods in the namespace if not provided)")), + mcp.WithString("label_selector", mcp.Description("Kubernetes label selector (e.g. 'app=myapp,env=prod' or 'app in (myapp,yourapp)'), use this option when you want to filter the pods by label (Optional, only applicable when name is not provided)"), mcp.Pattern("([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Top"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithIdempotentHintAnnotation(true), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsTop}, + {Tool: mcp.NewTool("pods_exec", + mcp.WithDescription("Execute a command in a Kubernetes Pod in the current or provided namespace with the provided name and command"), + mcp.WithString("namespace", mcp.Description("Namespace of the Pod where the command will be executed")), + mcp.WithString("name", mcp.Description("Name of the Pod where the command will be executed"), mcp.Required()), + mcp.WithArray("command", mcp.Description("Command to execute in the Pod container. "+ + "The first item is the command to be run, and the rest are the arguments to that command. "+ + `Example: ["ls", "-l", "/tmp"]`), + // TODO: manual fix to ensure that the items property gets initialized (Gemini) + // https://www.googlecloudcommunity.com/gc/AI-ML/Gemini-API-400-Bad-Request-Array-fields-breaks-function-calling/m-p/769835?nobounce + func(schema map[string]interface{}) { + schema["type"] = "array" + schema["items"] = map[string]interface{}{ + "type": "string", + } + }, + mcp.Required(), + ), + mcp.WithString("container", mcp.Description("Name of the Pod container where the command will be executed (Optional)")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Exec"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(true), // Depending on the Pod's entrypoint, executing certain commands may kill the Pod + mcp.WithIdempotentHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsExec}, + {Tool: mcp.NewTool("pods_log", + mcp.WithDescription("Get the logs of a Kubernetes Pod in the current or provided namespace with the provided name"), + mcp.WithString("namespace", mcp.Description("Namespace to get the Pod logs from")), + mcp.WithString("name", mcp.Description("Name of the Pod to get the logs from"), mcp.Required()), + mcp.WithString("container", mcp.Description("Name of the Pod container to get the logs from (Optional)")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Log"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsLog}, + {Tool: mcp.NewTool("pods_run", + mcp.WithDescription("Run a Kubernetes Pod in the current or provided namespace with the provided container image and optional name"), + mcp.WithString("namespace", mcp.Description("Namespace to run the Pod in")), + mcp.WithString("name", mcp.Description("Name of the Pod (Optional, random name if not provided)")), + mcp.WithString("image", mcp.Description("Container Image to run in the Pod"), mcp.Required()), + mcp.WithNumber("port", mcp.Description("TCP/IP port to expose from the Pod container (Optional, no port exposed if not provided)")), + // Tool annotations + mcp.WithTitleAnnotation("Pods: Run"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithIdempotentHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.podsRun}, + } +} + +func (s *Server) podsListInAllNamespaces(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + labelSelector := ctr.GetArguments()["labelSelector"] + resourceListOptions := kubernetes.ResourceListOptions{ + AsTable: s.configuration.ListOutput.AsTable(), + } + if labelSelector != nil { + resourceListOptions.LabelSelector = labelSelector.(string) + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsListInAllNamespaces(ctx, resourceListOptions) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list pods in all namespaces: %v", err)), nil + } + return NewTextResult(s.configuration.ListOutput.PrintObj(ret)), nil +} + +func (s *Server) podsListInNamespace(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + return NewTextResult("", errors.New("failed to list pods in namespace, missing argument namespace")), nil + } + resourceListOptions := kubernetes.ResourceListOptions{ + AsTable: s.configuration.ListOutput.AsTable(), + } + labelSelector := ctr.GetArguments()["labelSelector"] + if labelSelector != nil { + resourceListOptions.LabelSelector = labelSelector.(string) + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsListInNamespace(ctx, ns.(string), resourceListOptions) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list pods in namespace %s: %v", ns, err)), nil + } + return NewTextResult(s.configuration.ListOutput.PrintObj(ret)), nil +} + +func (s *Server) podsGet(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + ns = "" + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to get pod, missing argument name")), nil + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsGet(ctx, ns.(string), name.(string)) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get pod %s in namespace %s: %v", name, ns, err)), nil + } + return NewTextResult(output.MarshalYaml(ret)), nil +} + +func (s *Server) podsDelete(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + ns = "" + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to delete pod, missing argument name")), nil + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsDelete(ctx, ns.(string), name.(string)) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to delete pod %s in namespace %s: %v", name, ns, err)), nil + } + return NewTextResult(ret, err), nil +} + +func (s *Server) podsTop(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + podsTopOptions := kubernetes.PodsTopOptions{AllNamespaces: true} + if v, ok := ctr.GetArguments()["namespace"].(string); ok { + podsTopOptions.Namespace = v + } + if v, ok := ctr.GetArguments()["all_namespaces"].(bool); ok { + podsTopOptions.AllNamespaces = v + } + if v, ok := ctr.GetArguments()["name"].(string); ok { + podsTopOptions.Name = v + } + if v, ok := ctr.GetArguments()["label_selector"].(string); ok { + podsTopOptions.LabelSelector = v + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsTop(ctx, podsTopOptions) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get pods top: %v", err)), nil + } + buf := new(bytes.Buffer) + printer := metricsutil.NewTopCmdPrinter(buf) + err = printer.PrintPodMetrics(ret.Items, true, true, false, "", true) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get pods top: %v", err)), nil + } + return NewTextResult(buf.String(), nil), nil +} + +func (s *Server) podsExec(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + ns = "" + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to exec in pod, missing argument name")), nil + } + container := ctr.GetArguments()["container"] + if container == nil { + container = "" + } + commandArg := ctr.GetArguments()["command"] + command := make([]string, 0) + if _, ok := commandArg.([]interface{}); ok { + for _, cmd := range commandArg.([]interface{}) { + if _, ok := cmd.(string); ok { + command = append(command, cmd.(string)) + } + } + } else { + return NewTextResult("", errors.New("failed to exec in pod, invalid command argument")), nil + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsExec(ctx, ns.(string), name.(string), container.(string), command) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to exec in pod %s in namespace %s: %v", name, ns, err)), nil + } else if ret == "" { + ret = fmt.Sprintf("The executed command in pod %s in namespace %s has not produced any output", name, ns) + } + return NewTextResult(ret, err), nil +} + +func (s *Server) podsLog(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + ns = "" + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to get pod log, missing argument name")), nil + } + container := ctr.GetArguments()["container"] + if container == nil { + container = "" + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.PodsLog(ctx, ns.(string), name.(string), container.(string)) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get pod %s log in namespace %s: %v", name, ns, err)), nil + } else if ret == "" { + ret = fmt.Sprintf("The pod %s in namespace %s has not logged any message yet", name, ns) + } + return NewTextResult(ret, err), nil +} + +func (s *Server) podsRun(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + ns := ctr.GetArguments()["namespace"] + if ns == nil { + ns = "" + } + name := ctr.GetArguments()["name"] + if name == nil { + name = "" + } + image := ctr.GetArguments()["image"] + if image == nil { + return NewTextResult("", errors.New("failed to run pod, missing argument image")), nil + } + port := ctr.GetArguments()["port"] + if port == nil { + port = float64(0) + } + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + resources, err := derived.PodsRun(ctx, ns.(string), name.(string), image.(string), int32(port.(float64))) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to run pod %s in namespace %s: %v", name, ns, err)), nil + } + marshalledYaml, err := output.MarshalYaml(resources) + if err != nil { + err = fmt.Errorf("failed to run pod: %v", err) + } + return NewTextResult("# The following resources (YAML) have been created or updated successfully\n"+marshalledYaml, err), nil +} diff --git a/pkg 2/mcp/pods_exec_test.go b/pkg 2/mcp/pods_exec_test.go new file mode 100644 index 00000000..919e80b2 --- /dev/null +++ b/pkg 2/mcp/pods_exec_test.go @@ -0,0 +1,126 @@ +package mcp + +import ( + "bytes" + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/mark3labs/mcp-go/mcp" + "io" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "net/http" + "strings" + "testing" +) + +func TestPodsExec(t *testing.T) { + testCase(t, func(c *mcpContext) { + mockServer := NewMockServer() + defer mockServer.Close() + c.withKubeConfig(mockServer.config) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + if req.URL.Path != "/api/v1/namespaces/default/pods/pod-to-exec/exec" { + return + } + var stdin, stdout bytes.Buffer + ctx, err := createHTTPStreams(w, req, &StreamOptions{ + Stdin: &stdin, + Stdout: &stdout, + }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(err.Error())) + return + } + defer func(conn io.Closer) { _ = conn.Close() }(ctx.conn) + _, _ = io.WriteString(ctx.stdoutStream, "command:"+strings.Join(req.URL.Query()["command"], " ")+"\n") + _, _ = io.WriteString(ctx.stdoutStream, "container:"+strings.Join(req.URL.Query()["container"], " ")+"\n") + })) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + if req.URL.Path != "/api/v1/namespaces/default/pods/pod-to-exec" { + return + } + writeObject(w, &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "pod-to-exec", + }, + Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container-to-exec"}}}, + }) + })) + podsExecNilNamespace, err := c.callTool("pods_exec", map[string]interface{}{ + "name": "pod-to-exec", + "command": []interface{}{"ls", "-l"}, + }) + t.Run("pods_exec with name and nil namespace returns command output", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if podsExecNilNamespace.IsError { + t.Fatalf("call tool failed") + } + if !strings.Contains(podsExecNilNamespace.Content[0].(mcp.TextContent).Text, "command:ls -l\n") { + t.Errorf("unexpected result %v", podsExecNilNamespace.Content[0].(mcp.TextContent).Text) + } + }) + podsExecInNamespace, err := c.callTool("pods_exec", map[string]interface{}{ + "namespace": "default", + "name": "pod-to-exec", + "command": []interface{}{"ls", "-l"}, + }) + t.Run("pods_exec with name and namespace returns command output", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if podsExecInNamespace.IsError { + t.Fatalf("call tool failed") + } + if !strings.Contains(podsExecNilNamespace.Content[0].(mcp.TextContent).Text, "command:ls -l\n") { + t.Errorf("unexpected result %v", podsExecInNamespace.Content[0].(mcp.TextContent).Text) + } + }) + podsExecInNamespaceAndContainer, err := c.callTool("pods_exec", map[string]interface{}{ + "namespace": "default", + "name": "pod-to-exec", + "command": []interface{}{"ls", "-l"}, + "container": "a-specific-container", + }) + t.Run("pods_exec with name, namespace, and container returns command output", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if podsExecInNamespaceAndContainer.IsError { + t.Fatalf("call tool failed") + } + if !strings.Contains(podsExecInNamespaceAndContainer.Content[0].(mcp.TextContent).Text, "command:ls -l\n") { + t.Errorf("unexpected result %v", podsExecInNamespaceAndContainer.Content[0].(mcp.TextContent).Text) + } + if !strings.Contains(podsExecInNamespaceAndContainer.Content[0].(mcp.TextContent).Text, "container:a-specific-container\n") { + t.Errorf("expected container name not found %v", podsExecInNamespaceAndContainer.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsExecDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsRun, _ := c.callTool("pods_exec", map[string]interface{}{ + "namespace": "default", + "name": "pod-to-exec", + "command": []interface{}{"ls", "-l"}, + "container": "a-specific-container", + }) + t.Run("pods_exec has error", func(t *testing.T) { + if !podsRun.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_exec describes denial", func(t *testing.T) { + expectedMessage := "failed to exec in pod pod-to-exec in namespace default: resource not allowed: /v1, Kind=Pod" + if podsRun.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsRun.Content[0].(mcp.TextContent).Text) + } + }) + }) +} diff --git a/pkg 2/mcp/pods_test.go b/pkg 2/mcp/pods_test.go new file mode 100644 index 00000000..de61dbe7 --- /dev/null +++ b/pkg 2/mcp/pods_test.go @@ -0,0 +1,1051 @@ +package mcp + +import ( + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/output" + "regexp" + "strings" + "testing" + + "github.com/mark3labs/mcp-go/mcp" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "sigs.k8s.io/yaml" +) + +func TestPodsListInAllNamespaces(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + toolResult, err := c.callTool("pods_list", map[string]interface{}{}) + t.Run("pods_list returns pods list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + }) + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("pods_list has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("pods_list returns 3 items", func(t *testing.T) { + if len(decoded) != 3 { + t.Fatalf("invalid pods count, expected 3, got %v", len(decoded)) + } + }) + t.Run("pods_list returns pod in ns-1", func(t *testing.T) { + if decoded[1].GetName() != "a-pod-in-ns-1" { + t.Fatalf("invalid pod name, expected a-pod-in-ns-1, got %v", decoded[1].GetName()) + } + if decoded[1].GetNamespace() != "ns-1" { + t.Fatalf("invalid pod namespace, expected ns-1, got %v", decoded[1].GetNamespace()) + } + }) + t.Run("pods_list returns pod in ns-2", func(t *testing.T) { + if decoded[2].GetName() != "a-pod-in-ns-2" { + t.Fatalf("invalid pod name, expected a-pod-in-ns-2, got %v", decoded[2].GetName()) + } + if decoded[2].GetNamespace() != "ns-2" { + t.Fatalf("invalid pod namespace, expected ns-2, got %v", decoded[2].GetNamespace()) + } + }) + t.Run("pods_list omits managed fields", func(t *testing.T) { + if decoded[1].GetManagedFields() != nil { + t.Fatalf("managed fields should be omitted, got %v", decoded[0].GetManagedFields()) + } + }) + }) +} + +func TestPodsListInAllNamespacesUnauthorized(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + defer restoreAuth(c.ctx) + client := c.newKubernetesClient() + // Authorize user only for default/configured namespace + r, _ := client.RbacV1().Roles("default").Create(c.ctx, &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "allow-pods-list"}, + Rules: []rbacv1.PolicyRule{{ + Verbs: []string{"get", "list"}, + APIGroups: []string{""}, + Resources: []string{"pods"}, + }}, + }, metav1.CreateOptions{}) + _, _ = client.RbacV1().RoleBindings("default").Create(c.ctx, &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: "allow-pods-list"}, + Subjects: []rbacv1.Subject{{Kind: "User", Name: envTestUser.Name}}, + RoleRef: rbacv1.RoleRef{Kind: "Role", Name: r.Name}, + }, metav1.CreateOptions{}) + // Deny cluster by removing cluster rule + _ = client.RbacV1().ClusterRoles().Delete(c.ctx, "allow-all", metav1.DeleteOptions{}) + toolResult, err := c.callTool("pods_list", map[string]interface{}{}) + t.Run("pods_list returns pods list for default namespace only", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if toolResult.IsError { + t.Fatalf("call tool failed") + return + } + }) + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("pods_list has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + }) + t.Run("pods_list returns 1 items", func(t *testing.T) { + if len(decoded) != 1 { + t.Fatalf("invalid pods count, expected 1, got %v", len(decoded)) + return + } + }) + t.Run("pods_list returns pod in default", func(t *testing.T) { + if decoded[0].GetName() != "a-pod-in-default" { + t.Fatalf("invalid pod name, expected a-pod-in-default, got %v", decoded[0].GetName()) + return + } + if decoded[0].GetNamespace() != "default" { + t.Fatalf("invalid pod namespace, expected default, got %v", decoded[0].GetNamespace()) + return + } + }) + }) +} + +func TestPodsListInNamespace(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("pods_list_in_namespace with nil namespace returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_list_in_namespace", map[string]interface{}{}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to list pods in namespace, missing argument namespace" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + toolResult, err := c.callTool("pods_list_in_namespace", map[string]interface{}{ + "namespace": "ns-1", + }) + t.Run("pods_list_in_namespace returns pods list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if toolResult.IsError { + t.Fatalf("call tool failed") + } + }) + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + t.Run("pods_list_in_namespace has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("pods_list_in_namespace returns 1 items", func(t *testing.T) { + if len(decoded) != 1 { + t.Fatalf("invalid pods count, expected 1, got %v", len(decoded)) + } + }) + t.Run("pods_list_in_namespace returns pod in ns-1", func(t *testing.T) { + if decoded[0].GetName() != "a-pod-in-ns-1" { + t.Errorf("invalid pod name, expected a-pod-in-ns-1, got %v", decoded[0].GetName()) + } + if decoded[0].GetNamespace() != "ns-1" { + t.Errorf("invalid pod namespace, expected ns-1, got %v", decoded[0].GetNamespace()) + } + }) + t.Run("pods_list_in_namespace omits managed fields", func(t *testing.T) { + if decoded[0].GetManagedFields() != nil { + t.Fatalf("managed fields should be omitted, got %v", decoded[0].GetManagedFields()) + } + }) + }) +} + +func TestPodsListDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsList, _ := c.callTool("pods_list", map[string]interface{}{}) + t.Run("pods_list has error", func(t *testing.T) { + if !podsList.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_list describes denial", func(t *testing.T) { + expectedMessage := "failed to list pods in all namespaces: resource not allowed: /v1, Kind=Pod" + if podsList.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsList.Content[0].(mcp.TextContent).Text) + } + }) + podsListInNamespace, _ := c.callTool("pods_list_in_namespace", map[string]interface{}{"namespace": "ns-1"}) + t.Run("pods_list_in_namespace has error", func(t *testing.T) { + if !podsListInNamespace.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_list_in_namespace describes denial", func(t *testing.T) { + expectedMessage := "failed to list pods in namespace ns-1: resource not allowed: /v1, Kind=Pod" + if podsListInNamespace.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsListInNamespace.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsListAsTable(t *testing.T) { + testCaseWithContext(t, &mcpContext{listOutput: output.Table}, func(c *mcpContext) { + c.withEnvTest() + podsList, err := c.callTool("pods_list", map[string]interface{}{}) + t.Run("pods_list returns pods list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if podsList.IsError { + t.Fatalf("call tool failed") + } + }) + outPodsList := podsList.Content[0].(mcp.TextContent).Text + t.Run("pods_list returns table with 1 header and 3 rows", func(t *testing.T) { + lines := strings.Count(outPodsList, "\n") + if lines != 4 { + t.Fatalf("invalid line count, expected 4 (1 header, 3 row), got %v", lines) + } + }) + t.Run("pods_list_in_namespace returns column headers", func(t *testing.T) { + expectedHeaders := "NAMESPACE\\s+APIVERSION\\s+KIND\\s+NAME\\s+READY\\s+STATUS\\s+RESTARTS\\s+AGE\\s+IP\\s+NODE\\s+NOMINATED NODE\\s+READINESS GATES\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, outPodsList); !m || e != nil { + t.Fatalf("Expected headers '%s' not found in output:\n%s", expectedHeaders, outPodsList) + } + }) + t.Run("pods_list_in_namespace returns formatted row for a-pod-in-ns-1", func(t *testing.T) { + expectedRow := "(?ns-1)\\s+" + + "(?v1)\\s+" + + "(?Pod)\\s+" + + "(?a-pod-in-ns-1)\\s+" + + "(?0\\/1)\\s+" + + "(?Pending)\\s+" + + "(?0)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)" + if m, e := regexp.MatchString(expectedRow, outPodsList); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, outPodsList) + } + }) + t.Run("pods_list_in_namespace returns formatted row for a-pod-in-default", func(t *testing.T) { + expectedRow := "(?default)\\s+" + + "(?v1)\\s+" + + "(?Pod)\\s+" + + "(?a-pod-in-default)\\s+" + + "(?0\\/1)\\s+" + + "(?Pending)\\s+" + + "(?0)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?app=nginx)" + if m, e := regexp.MatchString(expectedRow, outPodsList); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, outPodsList) + } + }) + podsListInNamespace, err := c.callTool("pods_list_in_namespace", map[string]interface{}{ + "namespace": "ns-1", + }) + t.Run("pods_list_in_namespace returns pods list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsListInNamespace.IsError { + t.Fatalf("call tool failed") + } + }) + outPodsListInNamespace := podsListInNamespace.Content[0].(mcp.TextContent).Text + t.Run("pods_list_in_namespace returns table with 1 header and 1 row", func(t *testing.T) { + lines := strings.Count(outPodsListInNamespace, "\n") + if lines != 2 { + t.Fatalf("invalid line count, expected 2 (1 header, 1 row), got %v", lines) + } + }) + t.Run("pods_list_in_namespace returns column headers", func(t *testing.T) { + expectedHeaders := "NAMESPACE\\s+APIVERSION\\s+KIND\\s+NAME\\s+READY\\s+STATUS\\s+RESTARTS\\s+AGE\\s+IP\\s+NODE\\s+NOMINATED NODE\\s+READINESS GATES\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, outPodsListInNamespace); !m || e != nil { + t.Fatalf("Expected headers '%s' not found in output:\n%s", expectedHeaders, outPodsListInNamespace) + } + }) + t.Run("pods_list_in_namespace returns formatted row", func(t *testing.T) { + expectedRow := "(?ns-1)\\s+" + + "(?v1)\\s+" + + "(?Pod)\\s+" + + "(?a-pod-in-ns-1)\\s+" + + "(?0\\/1)\\s+" + + "(?Pending)\\s+" + + "(?0)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)\\s+" + + "(?)" + if m, e := regexp.MatchString(expectedRow, outPodsListInNamespace); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, outPodsListInNamespace) + } + }) + }) +} + +func TestPodsGet(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("pods_get with nil name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_get", map[string]interface{}{}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod, missing argument name" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_get with not found name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_get", map[string]interface{}{"name": "not-found"}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod not-found in namespace : pods \"not-found\" not found" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + podsGetNilNamespace, err := c.callTool("pods_get", map[string]interface{}{ + "name": "a-pod-in-default", + }) + t.Run("pods_get with name and nil namespace returns pod", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsGetNilNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + var decodedNilNamespace unstructured.Unstructured + err = yaml.Unmarshal([]byte(podsGetNilNamespace.Content[0].(mcp.TextContent).Text), &decodedNilNamespace) + t.Run("pods_get with name and nil namespace has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + }) + t.Run("pods_get with name and nil namespace returns pod in default", func(t *testing.T) { + if decodedNilNamespace.GetName() != "a-pod-in-default" { + t.Fatalf("invalid pod name, expected a-pod-in-default, got %v", decodedNilNamespace.GetName()) + return + } + if decodedNilNamespace.GetNamespace() != "default" { + t.Fatalf("invalid pod namespace, expected default, got %v", decodedNilNamespace.GetNamespace()) + return + } + }) + t.Run("pods_get with name and nil namespace omits managed fields", func(t *testing.T) { + if decodedNilNamespace.GetManagedFields() != nil { + t.Fatalf("managed fields should be omitted, got %v", decodedNilNamespace.GetManagedFields()) + return + } + }) + podsGetInNamespace, err := c.callTool("pods_get", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + }) + t.Run("pods_get with name and namespace returns pod", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsGetInNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + var decodedInNamespace unstructured.Unstructured + err = yaml.Unmarshal([]byte(podsGetInNamespace.Content[0].(mcp.TextContent).Text), &decodedInNamespace) + t.Run("pods_get with name and namespace has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + }) + t.Run("pods_get with name and namespace returns pod in ns-1", func(t *testing.T) { + if decodedInNamespace.GetName() != "a-pod-in-ns-1" { + t.Fatalf("invalid pod name, expected a-pod-in-ns-1, got %v", decodedInNamespace.GetName()) + return + } + if decodedInNamespace.GetNamespace() != "ns-1" { + t.Fatalf("invalid pod namespace, ns-1 ns-1, got %v", decodedInNamespace.GetNamespace()) + return + } + }) + }) +} + +func TestPodsGetDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsGet, _ := c.callTool("pods_get", map[string]interface{}{"name": "a-pod-in-default"}) + t.Run("pods_get has error", func(t *testing.T) { + if !podsGet.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_get describes denial", func(t *testing.T) { + expectedMessage := "failed to get pod a-pod-in-default in namespace : resource not allowed: /v1, Kind=Pod" + if podsGet.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsGet.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsDelete(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + // Errors + t.Run("pods_delete with nil name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_delete", map[string]interface{}{}) + if toolResult.IsError != true { + t.Errorf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete pod, missing argument name" { + t.Errorf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_delete with not found name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_delete", map[string]interface{}{"name": "not-found"}) + if toolResult.IsError != true { + t.Errorf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete pod not-found in namespace : pods \"not-found\" not found" { + t.Errorf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + // Default/nil Namespace + kc := c.newKubernetesClient() + _, _ = kc.CoreV1().Pods("default").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "a-pod-to-delete"}, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + podsDeleteNilNamespace, err := c.callTool("pods_delete", map[string]interface{}{ + "name": "a-pod-to-delete", + }) + t.Run("pods_delete with name and nil namespace returns success", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsDeleteNilNamespace.IsError { + t.Errorf("call tool failed") + return + } + if podsDeleteNilNamespace.Content[0].(mcp.TextContent).Text != "Pod deleted successfully" { + t.Errorf("invalid tool result content, got %v", podsDeleteNilNamespace.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_delete with name and nil namespace deletes Pod", func(t *testing.T) { + p, pErr := kc.CoreV1().Pods("default").Get(c.ctx, "a-pod-to-delete", metav1.GetOptions{}) + if pErr == nil && p != nil && p.DeletionTimestamp == nil { + t.Errorf("Pod not deleted") + return + } + }) + // Provided Namespace + _, _ = kc.CoreV1().Pods("ns-1").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "a-pod-to-delete-in-ns-1"}, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + podsDeleteInNamespace, err := c.callTool("pods_delete", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-to-delete-in-ns-1", + }) + t.Run("pods_delete with name and namespace returns success", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsDeleteInNamespace.IsError { + t.Errorf("call tool failed") + return + } + if podsDeleteInNamespace.Content[0].(mcp.TextContent).Text != "Pod deleted successfully" { + t.Errorf("invalid tool result content, got %v", podsDeleteInNamespace.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_delete with name and namespace deletes Pod", func(t *testing.T) { + p, pErr := kc.CoreV1().Pods("ns-1").Get(c.ctx, "a-pod-to-delete-in-ns-1", metav1.GetOptions{}) + if pErr == nil && p != nil && p.DeletionTimestamp == nil { + t.Errorf("Pod not deleted") + return + } + }) + // Managed Pod + managedLabels := map[string]string{ + "app.kubernetes.io/managed-by": "kubernetes-mcp-server", + "app.kubernetes.io/name": "a-manged-pod-to-delete", + } + _, _ = kc.CoreV1().Pods("default").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "a-managed-pod-to-delete", Labels: managedLabels}, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + _, _ = kc.CoreV1().Services("default").Create(c.ctx, &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "a-managed-service-to-delete", Labels: managedLabels}, + Spec: corev1.ServiceSpec{Selector: managedLabels, Ports: []corev1.ServicePort{{Port: 80}}}, + }, metav1.CreateOptions{}) + podsDeleteManaged, err := c.callTool("pods_delete", map[string]interface{}{ + "name": "a-managed-pod-to-delete", + }) + t.Run("pods_delete with managed pod returns success", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsDeleteManaged.IsError { + t.Errorf("call tool failed") + return + } + if podsDeleteManaged.Content[0].(mcp.TextContent).Text != "Pod deleted successfully" { + t.Errorf("invalid tool result content, got %v", podsDeleteManaged.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_delete with managed pod deletes Pod and Service", func(t *testing.T) { + p, pErr := kc.CoreV1().Pods("default").Get(c.ctx, "a-managed-pod-to-delete", metav1.GetOptions{}) + if pErr == nil && p != nil && p.DeletionTimestamp == nil { + t.Errorf("Pod not deleted") + return + } + s, sErr := kc.CoreV1().Services("default").Get(c.ctx, "a-managed-service-to-delete", metav1.GetOptions{}) + if sErr == nil && s != nil && s.DeletionTimestamp == nil { + t.Errorf("Service not deleted") + return + } + }) + }) +} + +func TestPodsDeleteDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsDelete, _ := c.callTool("pods_delete", map[string]interface{}{"name": "a-pod-in-default"}) + t.Run("pods_delete has error", func(t *testing.T) { + if !podsDelete.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_delete describes denial", func(t *testing.T) { + expectedMessage := "failed to delete pod a-pod-in-default in namespace : resource not allowed: /v1, Kind=Pod" + if podsDelete.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsDelete.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsDeleteInOpenShift(t *testing.T) { + testCaseWithContext(t, &mcpContext{before: inOpenShift, after: inOpenShiftClear}, func(c *mcpContext) { + managedLabels := map[string]string{ + "app.kubernetes.io/managed-by": "kubernetes-mcp-server", + "app.kubernetes.io/name": "a-manged-pod-to-delete", + } + kc := c.newKubernetesClient() + _, _ = kc.CoreV1().Pods("default").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "a-managed-pod-to-delete-in-openshift", Labels: managedLabels}, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + dynamicClient := dynamic.NewForConfigOrDie(envTestRestConfig) + _, _ = dynamicClient.Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}). + Namespace("default").Create(c.ctx, &unstructured.Unstructured{Object: map[string]interface{}{ + "apiVersion": "route.openshift.io/v1", + "kind": "Route", + "metadata": map[string]interface{}{ + "name": "a-managed-route-to-delete", + "labels": managedLabels, + }, + }}, metav1.CreateOptions{}) + podsDeleteManagedOpenShift, err := c.callTool("pods_delete", map[string]interface{}{ + "name": "a-managed-pod-to-delete-in-openshift", + }) + t.Run("pods_delete with managed pod in OpenShift returns success", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsDeleteManagedOpenShift.IsError { + t.Errorf("call tool failed") + return + } + if podsDeleteManagedOpenShift.Content[0].(mcp.TextContent).Text != "Pod deleted successfully" { + t.Errorf("invalid tool result content, got %v", podsDeleteManagedOpenShift.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_delete with managed pod in OpenShift deletes Pod and Route", func(t *testing.T) { + p, pErr := kc.CoreV1().Pods("default").Get(c.ctx, "a-managed-pod-to-delete-in-openshift", metav1.GetOptions{}) + if pErr == nil && p != nil && p.DeletionTimestamp == nil { + t.Errorf("Pod not deleted") + return + } + r, rErr := dynamicClient. + Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}). + Namespace("default").Get(c.ctx, "a-managed-route-to-delete", metav1.GetOptions{}) + if rErr == nil && r != nil && r.GetDeletionTimestamp() == nil { + t.Errorf("Route not deleted") + return + } + }) + }) +} + +func TestPodsLog(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("pods_log with nil name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_log", map[string]interface{}{}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod log, missing argument name" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("pods_log with not found name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_log", map[string]interface{}{"name": "not-found"}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod not-found log in namespace : pods \"not-found\" not found" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + podsLogNilNamespace, err := c.callTool("pods_log", map[string]interface{}{ + "name": "a-pod-in-default", + }) + t.Run("pods_log with name and nil namespace returns pod log", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsLogNilNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + podsLogInNamespace, err := c.callTool("pods_log", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + }) + t.Run("pods_log with name and namespace returns pod log", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsLogInNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + podsContainerLogInNamespace, err := c.callTool("pods_log", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + "container": "nginx", + }) + t.Run("pods_log with name, container and namespace returns pod log", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsContainerLogInNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + toolResult, err := c.callTool("pods_log", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + "container": "a-not-existing-container", + }) + t.Run("pods_log with non existing container returns error", func(t *testing.T) { + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod a-pod-in-ns-1 log in namespace ns-1: container a-not-existing-container is not valid for pod a-pod-in-ns-1" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + }) +} + +func TestPodsLogDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsLog, _ := c.callTool("pods_log", map[string]interface{}{"name": "a-pod-in-default"}) + t.Run("pods_log has error", func(t *testing.T) { + if !podsLog.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_log describes denial", func(t *testing.T) { + expectedMessage := "failed to get pod a-pod-in-default log in namespace : resource not allowed: /v1, Kind=Pod" + if podsLog.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsLog.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsRun(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("pods_run with nil image returns error", func(t *testing.T) { + toolResult, _ := c.callTool("pods_run", map[string]interface{}{}) + if toolResult.IsError != true { + t.Errorf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to run pod, missing argument image" { + t.Errorf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + podsRunNilNamespace, err := c.callTool("pods_run", map[string]interface{}{"image": "nginx"}) + t.Run("pods_run with image and nil namespace runs pod", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsRunNilNamespace.IsError { + t.Errorf("call tool failed") + return + } + }) + var decodedNilNamespace []unstructured.Unstructured + err = yaml.Unmarshal([]byte(podsRunNilNamespace.Content[0].(mcp.TextContent).Text), &decodedNilNamespace) + t.Run("pods_run with image and nil namespace has yaml content", func(t *testing.T) { + if err != nil { + t.Errorf("invalid tool result content %v", err) + return + } + }) + t.Run("pods_run with image and nil namespace returns 1 item (Pod)", func(t *testing.T) { + if len(decodedNilNamespace) != 1 { + t.Errorf("invalid pods count, expected 1, got %v", len(decodedNilNamespace)) + return + } + if decodedNilNamespace[0].GetKind() != "Pod" { + t.Errorf("invalid pod kind, expected Pod, got %v", decodedNilNamespace[0].GetKind()) + return + } + }) + t.Run("pods_run with image and nil namespace returns pod in default", func(t *testing.T) { + if decodedNilNamespace[0].GetNamespace() != "default" { + t.Errorf("invalid pod namespace, expected default, got %v", decodedNilNamespace[0].GetNamespace()) + return + } + }) + t.Run("pods_run with image and nil namespace returns pod with random name", func(t *testing.T) { + if !strings.HasPrefix(decodedNilNamespace[0].GetName(), "kubernetes-mcp-server-run-") { + t.Errorf("invalid pod name, expected random, got %v", decodedNilNamespace[0].GetName()) + return + } + }) + t.Run("pods_run with image and nil namespace returns pod with labels", func(t *testing.T) { + labels := decodedNilNamespace[0].Object["metadata"].(map[string]interface{})["labels"].(map[string]interface{}) + if labels["app.kubernetes.io/name"] == "" { + t.Errorf("invalid labels, expected app.kubernetes.io/name, got %v", labels) + return + } + if labels["app.kubernetes.io/component"] == "" { + t.Errorf("invalid labels, expected app.kubernetes.io/component, got %v", labels) + return + } + if labels["app.kubernetes.io/managed-by"] != "kubernetes-mcp-server" { + t.Errorf("invalid labels, expected app.kubernetes.io/managed-by, got %v", labels) + return + } + if labels["app.kubernetes.io/part-of"] != "kubernetes-mcp-server-run-sandbox" { + t.Errorf("invalid labels, expected app.kubernetes.io/part-of, got %v", labels) + return + } + }) + t.Run("pods_run with image and nil namespace returns pod with nginx container", func(t *testing.T) { + containers := decodedNilNamespace[0].Object["spec"].(map[string]interface{})["containers"].([]interface{}) + if containers[0].(map[string]interface{})["image"] != "nginx" { + t.Errorf("invalid container name, expected nginx, got %v", containers[0].(map[string]interface{})["image"]) + return + } + }) + + podsRunNamespaceAndPort, err := c.callTool("pods_run", map[string]interface{}{"image": "nginx", "port": 80}) + t.Run("pods_run with image, namespace, and port runs pod", func(t *testing.T) { + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsRunNamespaceAndPort.IsError { + t.Errorf("call tool failed") + return + } + }) + var decodedNamespaceAndPort []unstructured.Unstructured + err = yaml.Unmarshal([]byte(podsRunNamespaceAndPort.Content[0].(mcp.TextContent).Text), &decodedNamespaceAndPort) + t.Run("pods_run with image, namespace, and port has yaml content", func(t *testing.T) { + if err != nil { + t.Errorf("invalid tool result content %v", err) + return + } + }) + t.Run("pods_run with image, namespace, and port returns 2 items (Pod + Service)", func(t *testing.T) { + if len(decodedNamespaceAndPort) != 2 { + t.Errorf("invalid pods count, expected 2, got %v", len(decodedNamespaceAndPort)) + return + } + if decodedNamespaceAndPort[0].GetKind() != "Pod" { + t.Errorf("invalid pod kind, expected Pod, got %v", decodedNamespaceAndPort[0].GetKind()) + return + } + if decodedNamespaceAndPort[1].GetKind() != "Service" { + t.Errorf("invalid service kind, expected Service, got %v", decodedNamespaceAndPort[1].GetKind()) + return + } + }) + t.Run("pods_run with image, namespace, and port returns pod with port", func(t *testing.T) { + containers := decodedNamespaceAndPort[0].Object["spec"].(map[string]interface{})["containers"].([]interface{}) + ports := containers[0].(map[string]interface{})["ports"].([]interface{}) + if ports[0].(map[string]interface{})["containerPort"] != int64(80) { + t.Errorf("invalid container port, expected 80, got %v", ports[0].(map[string]interface{})["containerPort"]) + return + } + }) + t.Run("pods_run with image, namespace, and port returns service with port and selector", func(t *testing.T) { + ports := decodedNamespaceAndPort[1].Object["spec"].(map[string]interface{})["ports"].([]interface{}) + if ports[0].(map[string]interface{})["port"] != int64(80) { + t.Errorf("invalid service port, expected 80, got %v", ports[0].(map[string]interface{})["port"]) + return + } + if ports[0].(map[string]interface{})["targetPort"] != int64(80) { + t.Errorf("invalid service target port, expected 80, got %v", ports[0].(map[string]interface{})["targetPort"]) + return + } + selector := decodedNamespaceAndPort[1].Object["spec"].(map[string]interface{})["selector"].(map[string]interface{}) + if selector["app.kubernetes.io/name"] == "" { + t.Errorf("invalid service selector, expected app.kubernetes.io/name, got %v", selector) + return + } + if selector["app.kubernetes.io/managed-by"] != "kubernetes-mcp-server" { + t.Errorf("invalid service selector, expected app.kubernetes.io/managed-by, got %v", selector) + return + } + if selector["app.kubernetes.io/part-of"] != "kubernetes-mcp-server-run-sandbox" { + t.Errorf("invalid service selector, expected app.kubernetes.io/part-of, got %v", selector) + return + } + }) + }) +} + +func TestPodsRunDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Version: "v1", Kind: "Pod"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + podsRun, _ := c.callTool("pods_run", map[string]interface{}{"image": "nginx"}) + t.Run("pods_run has error", func(t *testing.T) { + if !podsRun.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_run describes denial", func(t *testing.T) { + expectedMessage := "failed to run pod in namespace : resource not allowed: /v1, Kind=Pod" + if podsRun.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsRun.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsRunInOpenShift(t *testing.T) { + testCaseWithContext(t, &mcpContext{before: inOpenShift, after: inOpenShiftClear}, func(c *mcpContext) { + t.Run("pods_run with image, namespace, and port returns route with port", func(t *testing.T) { + podsRunInOpenShift, err := c.callTool("pods_run", map[string]interface{}{"image": "nginx", "port": 80}) + if err != nil { + t.Errorf("call tool failed %v", err) + return + } + if podsRunInOpenShift.IsError { + t.Errorf("call tool failed") + return + } + var decodedPodServiceRoute []unstructured.Unstructured + err = yaml.Unmarshal([]byte(podsRunInOpenShift.Content[0].(mcp.TextContent).Text), &decodedPodServiceRoute) + if err != nil { + t.Errorf("invalid tool result content %v", err) + return + } + if len(decodedPodServiceRoute) != 3 { + t.Errorf("invalid pods count, expected 3, got %v", len(decodedPodServiceRoute)) + return + } + if decodedPodServiceRoute[2].GetKind() != "Route" { + t.Errorf("invalid route kind, expected Route, got %v", decodedPodServiceRoute[2].GetKind()) + return + } + targetPort := decodedPodServiceRoute[2].Object["spec"].(map[string]interface{})["port"].(map[string]interface{})["targetPort"].(int64) + if targetPort != 80 { + t.Errorf("invalid route target port, expected 80, got %v", targetPort) + return + } + }) + }) +} + +func TestPodsListWithLabelSelector(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + // Create pods with labels + _, _ = kc.CoreV1().Pods("default").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-with-labels", + Labels: map[string]string{"app": "test", "env": "dev"}, + }, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + _, _ = kc.CoreV1().Pods("ns-1").Create(c.ctx, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "another-pod-with-labels", + Labels: map[string]string{"app": "test", "env": "prod"}, + }, + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}}, + }, metav1.CreateOptions{}) + + // Test pods_list with label selector + t.Run("pods_list with label selector returns filtered pods", func(t *testing.T) { + toolResult, err := c.callTool("pods_list", map[string]interface{}{ + "labelSelector": "app=test", + }) + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if toolResult.IsError { + t.Fatalf("call tool failed") + return + } + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + if len(decoded) != 2 { + t.Fatalf("invalid pods count, expected 2, got %v", len(decoded)) + return + } + }) + + // Test pods_list_in_namespace with label selector + t.Run("pods_list_in_namespace with label selector returns filtered pods", func(t *testing.T) { + toolResult, err := c.callTool("pods_list_in_namespace", map[string]interface{}{ + "namespace": "ns-1", + "labelSelector": "env=prod", + }) + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if toolResult.IsError { + t.Fatalf("call tool failed") + return + } + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + if len(decoded) != 1 { + t.Fatalf("invalid pods count, expected 1, got %v", len(decoded)) + return + } + if decoded[0].GetName() != "another-pod-with-labels" { + t.Fatalf("invalid pod name, expected another-pod-with-labels, got %v", decoded[0].GetName()) + return + } + }) + + // Test multiple label selectors + t.Run("pods_list with multiple label selectors returns filtered pods", func(t *testing.T) { + toolResult, err := c.callTool("pods_list", map[string]interface{}{ + "labelSelector": "app=test,env=prod", + }) + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if toolResult.IsError { + t.Fatalf("call tool failed") + return + } + var decoded []unstructured.Unstructured + err = yaml.Unmarshal([]byte(toolResult.Content[0].(mcp.TextContent).Text), &decoded) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + if len(decoded) != 1 { + t.Fatalf("invalid pods count, expected 1, got %v", len(decoded)) + return + } + if decoded[0].GetName() != "another-pod-with-labels" { + t.Fatalf("invalid pod name, expected another-pod-with-labels, got %v", decoded[0].GetName()) + return + } + }) + }) +} diff --git a/pkg 2/mcp/pods_top_test.go b/pkg 2/mcp/pods_top_test.go new file mode 100644 index 00000000..0b63cac8 --- /dev/null +++ b/pkg 2/mcp/pods_top_test.go @@ -0,0 +1,248 @@ +package mcp + +import ( + "net/http" + "regexp" + "testing" + + "github.com/mark3labs/mcp-go/mcp" + + "github.com/containers/kubernetes-mcp-server/pkg/config" +) + +func TestPodsTopMetricsUnavailable(t *testing.T) { + testCase(t, func(c *mcpContext) { + mockServer := NewMockServer() + defer mockServer.Close() + c.withKubeConfig(mockServer.config) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + // Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-) + if req.URL.Path == "/api" { + _, _ = w.Write([]byte(`{"kind":"APIVersions","versions":[],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Groups) + if req.URL.Path == "/apis" { + _, _ = w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[]}`)) + return + } + })) + podsTopMetricsApiUnavailable, err := c.callTool("pods_top", map[string]interface{}{}) + t.Run("pods_top with metrics API not available", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if !podsTopMetricsApiUnavailable.IsError { + t.Errorf("call tool should have returned an error") + } + if podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text != "failed to get pods top: metrics API is not available" { + t.Errorf("call tool returned unexpected content: %s", podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text) + } + }) + }) +} + +func TestPodsTopMetricsAvailable(t *testing.T) { + testCase(t, func(c *mcpContext) { + mockServer := NewMockServer() + defer mockServer.Close() + c.withKubeConfig(mockServer.config) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + println("Request received:", req.Method, req.URL.Path) // TODO: REMOVE LINE + w.Header().Set("Content-Type", "application/json") + // Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-) + if req.URL.Path == "/api" { + _, _ = w.Write([]byte(`{"kind":"APIVersions","versions":["metrics.k8s.io/v1beta1"],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Groups) + if req.URL.Path == "/apis" { + _, _ = w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Resources) + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1" { + _, _ = w.Write([]byte(`{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"metrics.k8s.io/v1beta1","resources":[{"name":"pods","singularName":"","namespaced":true,"kind":"PodMetrics","verbs":["get","list"]}]}`)) + return + } + // Pod Metrics from all namespaces + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/pods" { + if req.URL.Query().Get("labelSelector") == "app=pod-ns-5-42" { + _, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` + + `{"metadata":{"name":"pod-ns-5-42","namespace":"ns-5"},"containers":[{"name":"container-1","usage":{"cpu":"42m","memory":"42Mi"}}]}` + + `]}`)) + } else { + _, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` + + `{"metadata":{"name":"pod-1","namespace":"default"},"containers":[{"name":"container-1","usage":{"cpu":"100m","memory":"200Mi"}},{"name":"container-2","usage":{"cpu":"200m","memory":"300Mi"}}]},` + + `{"metadata":{"name":"pod-2","namespace":"ns-1"},"containers":[{"name":"container-1-ns-1","usage":{"cpu":"300m","memory":"400Mi"}}]}` + + `]}`)) + + } + return + } + // Pod Metrics from configured namespace + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods" { + _, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` + + `{"metadata":{"name":"pod-1","namespace":"default"},"containers":[{"name":"container-1","usage":{"cpu":"10m","memory":"20Mi"}},{"name":"container-2","usage":{"cpu":"30m","memory":"40Mi"}}]}` + + `]}`)) + return + } + // Pod Metrics from ns-5 namespace + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods" { + _, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` + + `{"metadata":{"name":"pod-ns-5-1","namespace":"ns-5"},"containers":[{"name":"container-1","usage":{"cpu":"10m","memory":"20Mi"}}]}` + + `]}`)) + return + } + // Pod Metrics from ns-5 namespace with pod-ns-5-5 pod name + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods/pod-ns-5-5" { + _, _ = w.Write([]byte(`{"kind":"PodMetrics","apiVersion":"metrics.k8s.io/v1beta1",` + + `"metadata":{"name":"pod-ns-5-5","namespace":"ns-5"},` + + `"containers":[{"name":"container-1","usage":{"cpu":"13m","memory":"37Mi"}}]` + + `}`)) + } + })) + podsTopDefaults, err := c.callTool("pods_top", map[string]interface{}{}) + t.Run("pods_top defaults returns pod metrics from all namespaces", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + textContent := podsTopDefaults.Content[0].(mcp.TextContent).Text + if podsTopDefaults.IsError { + t.Fatalf("call tool failed %s", textContent) + } + expectedHeaders := regexp.MustCompile(`(?m)^\s*NAMESPACE\s+POD\s+NAME\s+CPU\(cores\)\s+MEMORY\(bytes\)\s*$`) + if !expectedHeaders.MatchString(textContent) { + t.Errorf("Expected headers '%s' not found in output:\n%s", expectedHeaders.String(), textContent) + } + expectedRows := []string{ + "default\\s+pod-1\\s+container-1\\s+100m\\s+200Mi", + "default\\s+pod-1\\s+container-2\\s+200m\\s+300Mi", + "ns-1\\s+pod-2\\s+container-1-ns-1\\s+300m\\s+400Mi", + } + for _, row := range expectedRows { + if !regexp.MustCompile(row).MatchString(textContent) { + t.Errorf("Expected row '%s' not found in output:\n%s", row, textContent) + } + } + expectedTotal := regexp.MustCompile(`(?m)^\s+600m\s+900Mi\s*$`) + if !expectedTotal.MatchString(textContent) { + t.Errorf("Expected total row '%s' not found in output:\n%s", expectedTotal.String(), textContent) + } + }) + podsTopConfiguredNamespace, err := c.callTool("pods_top", map[string]interface{}{ + "all_namespaces": false, + }) + t.Run("pods_top[allNamespaces=false] returns pod metrics from configured namespace", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + textContent := podsTopConfiguredNamespace.Content[0].(mcp.TextContent).Text + expectedRows := []string{ + "default\\s+pod-1\\s+container-1\\s+10m\\s+20Mi", + "default\\s+pod-1\\s+container-2\\s+30m\\s+40Mi", + } + for _, row := range expectedRows { + if !regexp.MustCompile(row).MatchString(textContent) { + t.Errorf("Expected row '%s' not found in output:\n%s", row, textContent) + } + } + expectedTotal := regexp.MustCompile(`(?m)^\s+40m\s+60Mi\s*$`) + if !expectedTotal.MatchString(textContent) { + t.Errorf("Expected total row '%s' not found in output:\n%s", expectedTotal.String(), textContent) + } + }) + podsTopNamespace, err := c.callTool("pods_top", map[string]interface{}{ + "namespace": "ns-5", + }) + t.Run("pods_top[namespace=ns-5] returns pod metrics from provided namespace", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + textContent := podsTopNamespace.Content[0].(mcp.TextContent).Text + expectedRow := regexp.MustCompile(`ns-5\s+pod-ns-5-1\s+container-1\s+10m\s+20Mi`) + if !expectedRow.MatchString(textContent) { + t.Errorf("Expected row '%s' not found in output:\n%s", expectedRow.String(), textContent) + } + expectedTotal := regexp.MustCompile(`(?m)^\s+10m\s+20Mi\s*$`) + if !expectedTotal.MatchString(textContent) { + t.Errorf("Expected total row '%s' not found in output:\n%s", expectedTotal.String(), textContent) + } + }) + podsTopNamespaceName, err := c.callTool("pods_top", map[string]interface{}{ + "namespace": "ns-5", + "name": "pod-ns-5-5", + }) + t.Run("pods_top[namespace=ns-5,name=pod-ns-5-5] returns pod metrics from provided namespace and name", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + textContent := podsTopNamespaceName.Content[0].(mcp.TextContent).Text + expectedRow := regexp.MustCompile(`ns-5\s+pod-ns-5-5\s+container-1\s+13m\s+37Mi`) + if !expectedRow.MatchString(textContent) { + t.Errorf("Expected row '%s' not found in output:\n%s", expectedRow.String(), textContent) + } + expectedTotal := regexp.MustCompile(`(?m)^\s+13m\s+37Mi\s*$`) + if !expectedTotal.MatchString(textContent) { + t.Errorf("Expected total row '%s' not found in output:\n%s", expectedTotal.String(), textContent) + } + }) + podsTopNamespaceLabelSelector, err := c.callTool("pods_top", map[string]interface{}{ + "label_selector": "app=pod-ns-5-42", + }) + t.Run("pods_top[label_selector=app=pod-ns-5-42] returns pod metrics from pods matching selector", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + textContent := podsTopNamespaceLabelSelector.Content[0].(mcp.TextContent).Text + expectedRow := regexp.MustCompile(`ns-5\s+pod-ns-5-42\s+container-1\s+42m\s+42Mi`) + if !expectedRow.MatchString(textContent) { + t.Errorf("Expected row '%s' not found in output:\n%s", expectedRow.String(), textContent) + } + expectedTotal := regexp.MustCompile(`(?m)^\s+42m\s+42Mi\s*$`) + if !expectedTotal.MatchString(textContent) { + t.Errorf("Expected total row '%s' not found in output:\n%s", expectedTotal.String(), textContent) + } + }) + }) +} + +func TestPodsTopDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{DeniedResources: []config.GroupVersionKind{{Group: "metrics.k8s.io", Version: "v1beta1"}}} + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + mockServer := NewMockServer() + defer mockServer.Close() + c.withKubeConfig(mockServer.config) + mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + // Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-) + if req.URL.Path == "/api" { + _, _ = w.Write([]byte(`{"kind":"APIVersions","versions":["metrics.k8s.io/v1beta1"],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Groups) + if req.URL.Path == "/apis" { + _, _ = w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[]}`)) + return + } + // Request Performed by DiscoveryClient to Kube API (Get API Resources) + if req.URL.Path == "/apis/metrics.k8s.io/v1beta1" { + _, _ = w.Write([]byte(`{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"metrics.k8s.io/v1beta1","resources":[{"name":"pods","singularName":"","namespaced":true,"kind":"PodMetrics","verbs":["get","list"]}]}`)) + return + } + })) + podsTop, _ := c.callTool("pods_top", map[string]interface{}{}) + t.Run("pods_run has error", func(t *testing.T) { + if !podsTop.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("pods_run describes denial", func(t *testing.T) { + expectedMessage := "failed to get pods top: resource not allowed: metrics.k8s.io/v1beta1, Kind=PodMetrics" + if podsTop.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, podsTop.Content[0].(mcp.TextContent).Text) + } + }) + }) +} diff --git a/pkg 2/mcp/profiles.go b/pkg 2/mcp/profiles.go new file mode 100644 index 00000000..6c0d9741 --- /dev/null +++ b/pkg 2/mcp/profiles.go @@ -0,0 +1,54 @@ +package mcp + +import ( + "slices" + + "github.com/mark3labs/mcp-go/server" +) + +type Profile interface { + GetName() string + GetDescription() string + GetTools(s *Server) []server.ServerTool +} + +var Profiles = []Profile{ + &FullProfile{}, +} + +var ProfileNames []string + +func ProfileFromString(name string) Profile { + for _, profile := range Profiles { + if profile.GetName() == name { + return profile + } + } + return nil +} + +type FullProfile struct{} + +func (p *FullProfile) GetName() string { + return "full" +} +func (p *FullProfile) GetDescription() string { + return "Complete profile with all tools and extended outputs" +} +func (p *FullProfile) GetTools(s *Server) []server.ServerTool { + return slices.Concat( + s.initConfiguration(), + s.initEvents(), + s.initNamespaces(), + s.initPods(), + s.initResources(), + s.initHelm(), + ) +} + +func init() { + ProfileNames = make([]string, 0) + for _, profile := range Profiles { + ProfileNames = append(ProfileNames, profile.GetName()) + } +} diff --git a/pkg 2/mcp/profiles_test.go b/pkg 2/mcp/profiles_test.go new file mode 100644 index 00000000..4973595c --- /dev/null +++ b/pkg 2/mcp/profiles_test.go @@ -0,0 +1,88 @@ +package mcp + +import ( + "github.com/mark3labs/mcp-go/mcp" + "slices" + "strings" + "testing" +) + +func TestFullProfileTools(t *testing.T) { + expectedNames := []string{ + "configuration_view", + "events_list", + "helm_install", + "helm_list", + "helm_uninstall", + "namespaces_list", + "pods_list", + "pods_list_in_namespace", + "pods_get", + "pods_delete", + "pods_top", + "pods_log", + "pods_run", + "pods_exec", + "resources_list", + "resources_get", + "resources_create_or_update", + "resources_delete", + } + mcpCtx := &mcpContext{profile: &FullProfile{}} + testCaseWithContext(t, mcpCtx, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + return + } + }) + nameSet := make(map[string]bool) + for _, tool := range tools.Tools { + nameSet[tool.Name] = true + } + for _, name := range expectedNames { + t.Run("ListTools has "+name+" tool", func(t *testing.T) { + if nameSet[name] != true { + t.Fatalf("tool %s not found", name) + return + } + }) + } + }) +} + +func TestFullProfileToolsInOpenShift(t *testing.T) { + mcpCtx := &mcpContext{ + profile: &FullProfile{}, + before: inOpenShift, + after: inOpenShiftClear, + } + testCaseWithContext(t, mcpCtx, func(c *mcpContext) { + tools, err := c.mcpClient.ListTools(c.ctx, mcp.ListToolsRequest{}) + t.Run("ListTools returns tools", func(t *testing.T) { + if err != nil { + t.Fatalf("call ListTools failed %v", err) + } + }) + t.Run("ListTools contains projects_list tool", func(t *testing.T) { + idx := slices.IndexFunc(tools.Tools, func(tool mcp.Tool) bool { + return tool.Name == "projects_list" + }) + if idx == -1 { + t.Fatalf("tool projects_list not found") + } + }) + t.Run("ListTools has resources_list tool with OpenShift hint", func(t *testing.T) { + idx := slices.IndexFunc(tools.Tools, func(tool mcp.Tool) bool { + return tool.Name == "resources_list" + }) + if idx == -1 { + t.Fatalf("tool resources_list not found") + } + if !strings.Contains(tools.Tools[idx].Description, ", route.openshift.io/v1 Route") { + t.Fatalf("tool resources_list does not have OpenShift hint, got %s", tools.Tools[9].Description) + } + }) + }) +} diff --git a/pkg 2/mcp/resources.go b/pkg 2/mcp/resources.go new file mode 100644 index 00000000..dfb99dd9 --- /dev/null +++ b/pkg 2/mcp/resources.go @@ -0,0 +1,258 @@ +package mcp + +import ( + "context" + "errors" + "fmt" + + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/containers/kubernetes-mcp-server/pkg/kubernetes" + "github.com/containers/kubernetes-mcp-server/pkg/output" +) + +func (s *Server) initResources() []server.ServerTool { + commonApiVersion := "v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress" + if s.k.IsOpenShift(context.Background()) { + commonApiVersion += ", route.openshift.io/v1 Route" + } + commonApiVersion = fmt.Sprintf("(common apiVersion and kind include: %s)", commonApiVersion) + return []server.ServerTool{ + {Tool: mcp.NewTool("resources_list", + mcp.WithDescription("List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector\n"+ + commonApiVersion), + mcp.WithString("apiVersion", + mcp.Description("apiVersion of the resources (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)"), + mcp.Required(), + ), + mcp.WithString("kind", + mcp.Description("kind of the resources (examples of valid kind are: Pod, Service, Deployment, Ingress)"), + mcp.Required(), + ), + mcp.WithString("namespace", + mcp.Description("Optional Namespace to retrieve the namespaced resources from (ignored in case of cluster scoped resources). If not provided, will list resources from all namespaces")), + mcp.WithString("labelSelector", + mcp.Description("Optional Kubernetes label selector (e.g. 'app=myapp,env=prod' or 'app in (myapp,yourapp)'), use this option when you want to filter the pods by label"), mcp.Pattern("([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]")), + // Tool annotations + mcp.WithTitleAnnotation("Resources: List"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.resourcesList}, + {Tool: mcp.NewTool("resources_get", + mcp.WithDescription("Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n"+ + commonApiVersion), + mcp.WithString("apiVersion", + mcp.Description("apiVersion of the resource (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)"), + mcp.Required(), + ), + mcp.WithString("kind", + mcp.Description("kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)"), + mcp.Required(), + ), + mcp.WithString("namespace", + mcp.Description("Optional Namespace to retrieve the namespaced resource from (ignored in case of cluster scoped resources). If not provided, will get resource from configured namespace"), + ), + mcp.WithString("name", mcp.Description("Name of the resource"), mcp.Required()), + // Tool annotations + mcp.WithTitleAnnotation("Resources: Get"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithDestructiveHintAnnotation(false), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.resourcesGet}, + {Tool: mcp.NewTool("resources_create_or_update", + mcp.WithDescription("Create or update a Kubernetes resource in the current cluster by providing a YAML or JSON representation of the resource\n"+ + commonApiVersion), + mcp.WithString("resource", + mcp.Description("A JSON or YAML containing a representation of the Kubernetes resource. Should include top-level fields such as apiVersion,kind,metadata, and spec"), + mcp.Required(), + ), + // Tool annotations + mcp.WithTitleAnnotation("Resources: Create or Update"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(true), + mcp.WithIdempotentHintAnnotation(true), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.resourcesCreateOrUpdate}, + {Tool: mcp.NewTool("resources_delete", + mcp.WithDescription("Delete a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n"+ + commonApiVersion), + mcp.WithString("apiVersion", + mcp.Description("apiVersion of the resource (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)"), + mcp.Required(), + ), + mcp.WithString("kind", + mcp.Description("kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)"), + mcp.Required(), + ), + mcp.WithString("namespace", + mcp.Description("Optional Namespace to delete the namespaced resource from (ignored in case of cluster scoped resources). If not provided, will delete resource from configured namespace"), + ), + mcp.WithString("name", mcp.Description("Name of the resource"), mcp.Required()), + // Tool annotations + mcp.WithTitleAnnotation("Resources: Delete"), + mcp.WithReadOnlyHintAnnotation(false), + mcp.WithDestructiveHintAnnotation(true), + mcp.WithIdempotentHintAnnotation(true), + mcp.WithOpenWorldHintAnnotation(true), + ), Handler: s.resourcesDelete}, + } +} + +func (s *Server) resourcesList(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + namespace := ctr.GetArguments()["namespace"] + if namespace == nil { + namespace = "" + } + labelSelector := ctr.GetArguments()["labelSelector"] + resourceListOptions := kubernetes.ResourceListOptions{ + AsTable: s.configuration.ListOutput.AsTable(), + } + + if labelSelector != nil { + l, ok := labelSelector.(string) + if !ok { + return NewTextResult("", fmt.Errorf("labelSelector is not a string")), nil + } + resourceListOptions.LabelSelector = l + } + gvk, err := parseGroupVersionKind(ctr.GetArguments()) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list resources, %s", err)), nil + } + + ns, ok := namespace.(string) + if !ok { + return NewTextResult("", fmt.Errorf("namespace is not a string")), nil + } + + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.ResourcesList(ctx, gvk, ns, resourceListOptions) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to list resources: %v", err)), nil + } + return NewTextResult(s.configuration.ListOutput.PrintObj(ret)), nil +} + +func (s *Server) resourcesGet(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + namespace := ctr.GetArguments()["namespace"] + if namespace == nil { + namespace = "" + } + gvk, err := parseGroupVersionKind(ctr.GetArguments()) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get resource, %s", err)), nil + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to get resource, missing argument name")), nil + } + + ns, ok := namespace.(string) + if !ok { + return NewTextResult("", fmt.Errorf("namespace is not a string")), nil + } + + n, ok := name.(string) + if !ok { + return NewTextResult("", fmt.Errorf("name is not a string")), nil + } + + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + ret, err := derived.ResourcesGet(ctx, gvk, ns, n) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to get resource: %v", err)), nil + } + return NewTextResult(output.MarshalYaml(ret)), nil +} + +func (s *Server) resourcesCreateOrUpdate(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + resource := ctr.GetArguments()["resource"] + if resource == nil || resource == "" { + return NewTextResult("", errors.New("failed to create or update resources, missing argument resource")), nil + } + + r, ok := resource.(string) + if !ok { + return NewTextResult("", fmt.Errorf("resource is not a string")), nil + } + + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + resources, err := derived.ResourcesCreateOrUpdate(ctx, r) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to create or update resources: %v", err)), nil + } + marshalledYaml, err := output.MarshalYaml(resources) + if err != nil { + err = fmt.Errorf("failed to create or update resources:: %v", err) + } + return NewTextResult("# The following resources (YAML) have been created or updated successfully\n"+marshalledYaml, err), nil +} + +func (s *Server) resourcesDelete(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) { + namespace := ctr.GetArguments()["namespace"] + if namespace == nil { + namespace = "" + } + gvk, err := parseGroupVersionKind(ctr.GetArguments()) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to delete resource, %s", err)), nil + } + name := ctr.GetArguments()["name"] + if name == nil { + return NewTextResult("", errors.New("failed to delete resource, missing argument name")), nil + } + + ns, ok := namespace.(string) + if !ok { + return NewTextResult("", fmt.Errorf("namespace is not a string")), nil + } + + n, ok := name.(string) + if !ok { + return NewTextResult("", fmt.Errorf("name is not a string")), nil + } + + derived, err := s.k.Derived(ctx) + if err != nil { + return nil, err + } + err = derived.ResourcesDelete(ctx, gvk, ns, n) + if err != nil { + return NewTextResult("", fmt.Errorf("failed to delete resource: %v", err)), nil + } + return NewTextResult("Resource deleted successfully", err), nil +} + +func parseGroupVersionKind(arguments map[string]interface{}) (*schema.GroupVersionKind, error) { + apiVersion := arguments["apiVersion"] + if apiVersion == nil { + return nil, errors.New("missing argument apiVersion") + } + kind := arguments["kind"] + if kind == nil { + return nil, errors.New("missing argument kind") + } + + a, ok := apiVersion.(string) + if !ok { + return nil, fmt.Errorf("name is not a string") + } + + gv, err := schema.ParseGroupVersion(a) + if err != nil { + return nil, errors.New("invalid argument apiVersion") + } + return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind.(string)}, nil +} diff --git a/pkg 2/mcp/resources_test.go b/pkg 2/mcp/resources_test.go new file mode 100644 index 00000000..ebd44195 --- /dev/null +++ b/pkg 2/mcp/resources_test.go @@ -0,0 +1,791 @@ +package mcp + +import ( + "regexp" + "strings" + "testing" + + "github.com/mark3labs/mcp-go/mcp" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "sigs.k8s.io/yaml" + + "github.com/containers/kubernetes-mcp-server/pkg/config" + "github.com/containers/kubernetes-mcp-server/pkg/output" +) + +func TestResourcesList(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("resources_list with missing apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_list", map[string]interface{}{}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to list resources, missing argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + t.Run("resources_list with missing kind returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "v1"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to list resources, missing argument kind" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + t.Run("resources_list with invalid apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "invalid/api/version", "kind": "Pod"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to list resources, invalid argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + t.Run("resources_list with nonexistent apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "custom.non.existent.example.com/v1", "kind": "Custom"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + } + if toolResult.Content[0].(mcp.TextContent).Text != `failed to list resources: no matches for kind "Custom" in version "custom.non.existent.example.com/v1"` { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + } + }) + namespaces, err := c.callTool("resources_list", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}) + t.Run("resources_list returns namespaces", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if namespaces.IsError { + t.Fatalf("call tool failed") + return + } + }) + var decodedNamespaces []unstructured.Unstructured + err = yaml.Unmarshal([]byte(namespaces.Content[0].(mcp.TextContent).Text), &decodedNamespaces) + t.Run("resources_list has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + } + }) + t.Run("resources_list returns more than 2 items", func(t *testing.T) { + if len(decodedNamespaces) < 3 { + t.Fatalf("invalid namespace count, expected >2, got %v", len(decodedNamespaces)) + } + }) + + // Test label selector functionality + t.Run("resources_list with label selector returns filtered pods", func(t *testing.T) { + + // List pods with label selector + result, err := c.callTool("resources_list", map[string]interface{}{ + "apiVersion": "v1", + "kind": "Pod", + "namespace": "default", + "labelSelector": "app=nginx", + }) + + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if result.IsError { + t.Fatalf("call tool failed") + return + } + + var decodedPods []unstructured.Unstructured + err = yaml.Unmarshal([]byte(result.Content[0].(mcp.TextContent).Text), &decodedPods) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + + // Verify only the pod with matching label is returned + if len(decodedPods) != 1 { + t.Fatalf("expected 1 pod, got %d", len(decodedPods)) + return + } + + if decodedPods[0].GetName() != "a-pod-in-default" { + t.Fatalf("expected pod-with-label, got %s", decodedPods[0].GetName()) + return + } + + // Test that multiple label selectors work + result, err = c.callTool("resources_list", map[string]interface{}{ + "apiVersion": "v1", + "kind": "Pod", + "namespace": "default", + "labelSelector": "test-label=test-value,another=value", + }) + + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if result.IsError { + t.Fatalf("call tool failed") + return + } + + err = yaml.Unmarshal([]byte(result.Content[0].(mcp.TextContent).Text), &decodedPods) + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + + // Verify no pods match multiple label selector + if len(decodedPods) != 0 { + t.Fatalf("expected 0 pods, got %d", len(decodedPods)) + return + } + }) + }) +} + +func TestResourcesListDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{ + DeniedResources: []config.GroupVersionKind{ + {Version: "v1", Kind: "Secret"}, + {Group: "rbac.authorization.k8s.io", Version: "v1"}, + }, + } + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + deniedByKind, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "v1", "kind": "Secret"}) + t.Run("resources_list (denied by kind) has error", func(t *testing.T) { + if !deniedByKind.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_list (denied by kind) describes denial", func(t *testing.T) { + expectedMessage := "failed to list resources: resource not allowed: /v1, Kind=Secret" + if deniedByKind.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + deniedByGroup, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role"}) + t.Run("resources_list (denied by group) has error", func(t *testing.T) { + if !deniedByGroup.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_list (denied by group) describes denial", func(t *testing.T) { + expectedMessage := "failed to list resources: resource not allowed: rbac.authorization.k8s.io/v1, Kind=Role" + if deniedByGroup.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + allowedResource, _ := c.callTool("resources_list", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}) + t.Run("resources_list (not denied) returns list", func(t *testing.T) { + if allowedResource.IsError { + t.Fatalf("call tool should not fail") + } + }) + }) +} + +func TestResourcesListAsTable(t *testing.T) { + testCaseWithContext(t, &mcpContext{listOutput: output.Table, before: inOpenShift, after: inOpenShiftClear}, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + _, _ = kc.CoreV1().ConfigMaps("default").Create(t.Context(), &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Name: "a-configmap-to-list-as-table", Labels: map[string]string{"resource": "config-map"}}, + Data: map[string]string{"key": "value"}, + }, metav1.CreateOptions{}) + configMapList, err := c.callTool("resources_list", map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap"}) + t.Run("resources_list returns ConfigMap list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if configMapList.IsError { + t.Fatalf("call tool failed") + } + }) + outConfigMapList := configMapList.Content[0].(mcp.TextContent).Text + t.Run("resources_list returns column headers for ConfigMap list", func(t *testing.T) { + expectedHeaders := "NAMESPACE\\s+APIVERSION\\s+KIND\\s+NAME\\s+DATA\\s+AGE\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, outConfigMapList); !m || e != nil { + t.Fatalf("Expected headers '%s' not found in output:\n%s", expectedHeaders, outConfigMapList) + } + }) + t.Run("resources_list returns formatted row for a-configmap-to-list-as-table", func(t *testing.T) { + expectedRow := "(?default)\\s+" + + "(?v1)\\s+" + + "(?ConfigMap)\\s+" + + "(?a-configmap-to-list-as-table)\\s+" + + "(?1)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?resource=config-map)" + if m, e := regexp.MatchString(expectedRow, outConfigMapList); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, outConfigMapList) + } + }) + // Custom Resource List + _, _ = dynamic.NewForConfigOrDie(envTestRestConfig). + Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}). + Namespace("default"). + Create(c.ctx, &unstructured.Unstructured{Object: map[string]interface{}{ + "apiVersion": "route.openshift.io/v1", + "kind": "Route", + "metadata": map[string]interface{}{ + "name": "an-openshift-route-to-list-as-table", + }, + }}, metav1.CreateOptions{}) + routeList, err := c.callTool("resources_list", map[string]interface{}{"apiVersion": "route.openshift.io/v1", "kind": "Route"}) + t.Run("resources_list returns Route list", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + } + if routeList.IsError { + t.Fatalf("call tool failed") + } + }) + outRouteList := routeList.Content[0].(mcp.TextContent).Text + t.Run("resources_list returns column headers for Route list", func(t *testing.T) { + expectedHeaders := "NAMESPACE\\s+APIVERSION\\s+KIND\\s+NAME\\s+AGE\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, outRouteList); !m || e != nil { + t.Fatalf("Expected headers '%s' not found in output:\n%s", expectedHeaders, outRouteList) + } + }) + t.Run("resources_list returns formatted row for an-openshift-route-to-list-as-table", func(t *testing.T) { + expectedRow := "(?default)\\s+" + + "(?route.openshift.io/v1)\\s+" + + "(?Route)\\s+" + + "(?an-openshift-route-to-list-as-table)\\s+" + + "(?(\\d+m)?(\\d+s)?)\\s+" + + "(?)" + if m, e := regexp.MatchString(expectedRow, outRouteList); !m || e != nil { + t.Fatalf("Expected row '%s' not found in output:\n%s", expectedRow, outRouteList) + } + }) + }) +} + +func TestResourcesGet(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("resources_get with missing apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_get", map[string]interface{}{}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get resource, missing argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_get with missing kind returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "v1"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get resource, missing argument kind" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_get with invalid apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "invalid/api/version", "kind": "Pod", "name": "a-pod"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get resource, invalid argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_get with nonexistent apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "custom.non.existent.example.com/v1", "kind": "Custom", "name": "a-custom"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != `failed to get resource: no matches for kind "Custom" in version "custom.non.existent.example.com/v1"` { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_get with missing name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get resource, missing argument name" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + namespace, err := c.callTool("resources_get", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace", "name": "default"}) + t.Run("resources_get returns namespace", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if namespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + var decodedNamespace unstructured.Unstructured + err = yaml.Unmarshal([]byte(namespace.Content[0].(mcp.TextContent).Text), &decodedNamespace) + t.Run("resources_get has yaml content", func(t *testing.T) { + if err != nil { + t.Fatalf("invalid tool result content %v", err) + return + } + }) + t.Run("resources_get returns default namespace", func(t *testing.T) { + if decodedNamespace.GetName() != "default" { + t.Fatalf("invalid namespace name, expected default, got %v", decodedNamespace.GetName()) + return + } + }) + }) +} + +func TestResourcesGetDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{ + DeniedResources: []config.GroupVersionKind{ + {Version: "v1", Kind: "Secret"}, + {Group: "rbac.authorization.k8s.io", Version: "v1"}, + }, + } + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + _, _ = kc.CoreV1().Secrets("default").Create(c.ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: "denied-secret"}, + }, metav1.CreateOptions{}) + _, _ = kc.RbacV1().Roles("default").Create(c.ctx, &v1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "denied-role"}, + }, metav1.CreateOptions{}) + deniedByKind, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "v1", "kind": "Secret", "namespace": "default", "name": "denied-secret"}) + t.Run("resources_get (denied by kind) has error", func(t *testing.T) { + if !deniedByKind.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_get (denied by kind) describes denial", func(t *testing.T) { + expectedMessage := "failed to get resource: resource not allowed: /v1, Kind=Secret" + if deniedByKind.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + deniedByGroup, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", "namespace": "default", "name": "denied-role"}) + t.Run("resources_get (denied by group) has error", func(t *testing.T) { + if !deniedByGroup.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_get (denied by group) describes denial", func(t *testing.T) { + expectedMessage := "failed to get resource: resource not allowed: rbac.authorization.k8s.io/v1, Kind=Role" + if deniedByGroup.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + allowedResource, _ := c.callTool("resources_get", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace", "name": "default"}) + t.Run("resources_get (not denied) returns resource", func(t *testing.T) { + if allowedResource.IsError { + t.Fatalf("call tool should not fail") + } + }) + }) +} + +func TestResourcesCreateOrUpdate(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("resources_create_or_update with nil resource returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_create_or_update", map[string]interface{}{}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to create or update resources, missing argument resource" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_create_or_update with empty resource returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_create_or_update", map[string]interface{}{"resource": ""}) + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to create or update resources, missing argument resource" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + client := c.newKubernetesClient() + configMapYaml := "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: a-cm-created-or-updated\n namespace: default\n" + resourcesCreateOrUpdateCm1, err := c.callTool("resources_create_or_update", map[string]interface{}{"resource": configMapYaml}) + t.Run("resources_create_or_update with valid namespaced yaml resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesCreateOrUpdateCm1.IsError { + t.Errorf("call tool failed") + return + } + }) + var decodedCreateOrUpdateCm1 []unstructured.Unstructured + err = yaml.Unmarshal([]byte(resourcesCreateOrUpdateCm1.Content[0].(mcp.TextContent).Text), &decodedCreateOrUpdateCm1) + t.Run("resources_create_or_update with valid namespaced yaml resource returns yaml content", func(t *testing.T) { + if err != nil { + t.Errorf("invalid tool result content %v", err) + return + } + if !strings.HasPrefix(resourcesCreateOrUpdateCm1.Content[0].(mcp.TextContent).Text, "# The following resources (YAML) have been created or updated successfully") { + t.Errorf("Excpected success message, got %v", resourcesCreateOrUpdateCm1.Content[0].(mcp.TextContent).Text) + return + } + if len(decodedCreateOrUpdateCm1) != 1 { + t.Errorf("invalid resource count, expected 1, got %v", len(decodedCreateOrUpdateCm1)) + return + } + if decodedCreateOrUpdateCm1[0].GetName() != "a-cm-created-or-updated" { + t.Errorf("invalid resource name, expected a-cm-created-or-updated, got %v", decodedCreateOrUpdateCm1[0].GetName()) + return + } + if decodedCreateOrUpdateCm1[0].GetUID() == "" { + t.Errorf("invalid uid, got %v", decodedCreateOrUpdateCm1[0].GetUID()) + return + } + }) + t.Run("resources_create_or_update with valid namespaced yaml resource creates ConfigMap", func(t *testing.T) { + cm, _ := client.CoreV1().ConfigMaps("default").Get(c.ctx, "a-cm-created-or-updated", metav1.GetOptions{}) + if cm == nil { + t.Fatalf("ConfigMap not found") + return + } + }) + configMapJson := "{\"apiVersion\": \"v1\", \"kind\": \"ConfigMap\", \"metadata\": {\"name\": \"a-cm-created-or-updated-2\", \"namespace\": \"default\"}}" + resourcesCreateOrUpdateCm2, err := c.callTool("resources_create_or_update", map[string]interface{}{"resource": configMapJson}) + t.Run("resources_create_or_update with valid namespaced json resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesCreateOrUpdateCm2.IsError { + t.Fatalf("call tool failed") + return + } + }) + t.Run("resources_create_or_update with valid namespaced json resource creates config map", func(t *testing.T) { + cm, _ := client.CoreV1().ConfigMaps("default").Get(c.ctx, "a-cm-created-or-updated-2", metav1.GetOptions{}) + if cm == nil { + t.Fatalf("ConfigMap not found") + return + } + }) + customResourceDefinitionJson := ` + { + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "CustomResourceDefinition", + "metadata": {"name": "customs.example.com"}, + "spec": { + "group": "example.com", + "versions": [{ + "name": "v1","served": true,"storage": true, + "schema": {"openAPIV3Schema": {"type": "object"}} + }], + "scope": "Namespaced", + "names": {"plural": "customs","singular": "custom","kind": "Custom"} + } + }` + resourcesCreateOrUpdateCrd, err := c.callTool("resources_create_or_update", map[string]interface{}{"resource": customResourceDefinitionJson}) + t.Run("resources_create_or_update with valid cluster-scoped json resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesCreateOrUpdateCrd.IsError { + t.Fatalf("call tool failed") + return + } + }) + t.Run("resources_create_or_update with valid cluster-scoped json resource creates custom resource definition", func(t *testing.T) { + apiExtensionsV1Client := c.newApiExtensionsClient() + _, err = apiExtensionsV1Client.CustomResourceDefinitions().Get(c.ctx, "customs.example.com", metav1.GetOptions{}) + if err != nil { + t.Fatalf("custom resource definition not found") + return + } + }) + c.crdWaitUntilReady("customs.example.com") + customJson := "{\"apiVersion\": \"example.com/v1\", \"kind\": \"Custom\", \"metadata\": {\"name\": \"a-custom-resource\"}}" + resourcesCreateOrUpdateCustom, err := c.callTool("resources_create_or_update", map[string]interface{}{"resource": customJson}) + t.Run("resources_create_or_update with valid namespaced json resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesCreateOrUpdateCustom.IsError { + t.Fatalf("call tool failed, got: %v", resourcesCreateOrUpdateCustom.Content) + return + } + }) + t.Run("resources_create_or_update with valid namespaced json resource creates custom resource", func(t *testing.T) { + dynamicClient := dynamic.NewForConfigOrDie(envTestRestConfig) + _, err = dynamicClient. + Resource(schema.GroupVersionResource{Group: "example.com", Version: "v1", Resource: "customs"}). + Namespace("default"). + Get(c.ctx, "a-custom-resource", metav1.GetOptions{}) + if err != nil { + t.Fatalf("custom resource not found") + return + } + }) + customJsonUpdated := "{\"apiVersion\": \"example.com/v1\", \"kind\": \"Custom\", \"metadata\": {\"name\": \"a-custom-resource\",\"annotations\": {\"updated\": \"true\"}}}" + resourcesCreateOrUpdateCustomUpdated, err := c.callTool("resources_create_or_update", map[string]interface{}{"resource": customJsonUpdated}) + t.Run("resources_create_or_update with valid namespaced json resource updates custom resource", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesCreateOrUpdateCustomUpdated.IsError { + t.Fatalf("call tool failed") + return + } + }) + t.Run("resources_create_or_update with valid namespaced json resource updates custom resource", func(t *testing.T) { + dynamicClient := dynamic.NewForConfigOrDie(envTestRestConfig) + customResource, _ := dynamicClient. + Resource(schema.GroupVersionResource{Group: "example.com", Version: "v1", Resource: "customs"}). + Namespace("default"). + Get(c.ctx, "a-custom-resource", metav1.GetOptions{}) + if customResource == nil { + t.Fatalf("custom resource not found") + return + } + annotations := customResource.GetAnnotations() + if annotations == nil || annotations["updated"] != "true" { + t.Fatalf("custom resource not updated") + return + } + }) + }) +} + +func TestResourcesCreateOrUpdateDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{ + DeniedResources: []config.GroupVersionKind{ + {Version: "v1", Kind: "Secret"}, + {Group: "rbac.authorization.k8s.io", Version: "v1"}, + }, + } + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + secretYaml := "apiVersion: v1\nkind: Secret\nmetadata:\n name: a-denied-secret\n namespace: default\n" + deniedByKind, _ := c.callTool("resources_create_or_update", map[string]interface{}{"resource": secretYaml}) + t.Run("resources_create_or_update (denied by kind) has error", func(t *testing.T) { + if !deniedByKind.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_create_or_update (denied by kind) describes denial", func(t *testing.T) { + expectedMessage := "failed to create or update resources: resource not allowed: /v1, Kind=Secret" + if deniedByKind.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + roleYaml := "apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n name: a-denied-role\n namespace: default\n" + deniedByGroup, _ := c.callTool("resources_create_or_update", map[string]interface{}{"resource": roleYaml}) + t.Run("resources_create_or_update (denied by group) has error", func(t *testing.T) { + if !deniedByGroup.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_create_or_update (denied by group) describes denial", func(t *testing.T) { + expectedMessage := "failed to create or update resources: resource not allowed: rbac.authorization.k8s.io/v1, Kind=Role" + if deniedByGroup.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + configMapYaml := "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: a-cm-created-or-updated\n namespace: default\n" + allowedResource, _ := c.callTool("resources_create_or_update", map[string]interface{}{"resource": configMapYaml}) + t.Run("resources_create_or_update (not denied) creates or updates resource", func(t *testing.T) { + if allowedResource.IsError { + t.Fatalf("call tool should not fail") + } + }) + }) +} + +func TestResourcesDelete(t *testing.T) { + testCase(t, func(c *mcpContext) { + c.withEnvTest() + t.Run("resources_delete with missing apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete resource, missing argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with missing kind returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete resource, missing argument kind" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with invalid apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "invalid/api/version", "kind": "Pod", "name": "a-pod"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete resource, invalid argument apiVersion" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with nonexistent apiVersion returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "custom.non.existent.example.com/v1", "kind": "Custom", "name": "a-custom"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != `failed to delete resource: no matches for kind "Custom" in version "custom.non.existent.example.com/v1"` { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with missing name returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to delete resource, missing argument name" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with nonexistent resource returns error", func(t *testing.T) { + toolResult, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap", "name": "nonexistent-configmap"}) + if !toolResult.IsError { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != `failed to delete resource: configmaps "nonexistent-configmap" not found` { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) + resourcesDeleteCm, err := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap", "name": "a-configmap-to-delete"}) + t.Run("resources_delete with valid namespaced resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesDeleteCm.IsError { + t.Fatalf("call tool failed") + return + } + if resourcesDeleteCm.Content[0].(mcp.TextContent).Text != "Resource deleted successfully" { + t.Fatalf("invalid tool result content got: %v", resourcesDeleteCm.Content[0].(mcp.TextContent).Text) + return + } + }) + client := c.newKubernetesClient() + t.Run("resources_delete with valid namespaced resource deletes ConfigMap", func(t *testing.T) { + _, err := client.CoreV1().ConfigMaps("default").Get(c.ctx, "a-configmap-to-delete", metav1.GetOptions{}) + if err == nil { + t.Fatalf("ConfigMap not deleted") + return + } + }) + resourcesDeleteNamespace, err := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "Namespace", "name": "ns-to-delete"}) + t.Run("resources_delete with valid namespaced resource returns success", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if resourcesDeleteNamespace.IsError { + t.Fatalf("call tool failed") + return + } + if resourcesDeleteNamespace.Content[0].(mcp.TextContent).Text != "Resource deleted successfully" { + t.Fatalf("invalid tool result content got: %v", resourcesDeleteNamespace.Content[0].(mcp.TextContent).Text) + return + } + }) + t.Run("resources_delete with valid namespaced resource deletes Namespace", func(t *testing.T) { + ns, err := client.CoreV1().Namespaces().Get(c.ctx, "ns-to-delete", metav1.GetOptions{}) + if err == nil && ns != nil && ns.DeletionTimestamp == nil { + t.Fatalf("Namespace not deleted") + return + } + }) + }) +} + +func TestResourcesDeleteDenied(t *testing.T) { + deniedResourcesServer := &config.StaticConfig{ + DeniedResources: []config.GroupVersionKind{ + {Version: "v1", Kind: "Secret"}, + {Group: "rbac.authorization.k8s.io", Version: "v1"}, + }, + } + testCaseWithContext(t, &mcpContext{staticConfig: deniedResourcesServer}, func(c *mcpContext) { + c.withEnvTest() + kc := c.newKubernetesClient() + _, _ = kc.CoreV1().ConfigMaps("default").Create(c.ctx, &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Name: "allowed-configmap-to-delete"}, + }, metav1.CreateOptions{}) + deniedByKind, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "Secret", "namespace": "default", "name": "denied-secret"}) + t.Run("resources_delete (denied by kind) has error", func(t *testing.T) { + if !deniedByKind.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_delete (denied by kind) describes denial", func(t *testing.T) { + expectedMessage := "failed to delete resource: resource not allowed: /v1, Kind=Secret" + if deniedByKind.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + deniedByGroup, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", "namespace": "default", "name": "denied-role"}) + t.Run("resources_delete (denied by group) has error", func(t *testing.T) { + if !deniedByGroup.IsError { + t.Fatalf("call tool should fail") + } + }) + t.Run("resources_delete (denied by group) describes denial", func(t *testing.T) { + expectedMessage := "failed to delete resource: resource not allowed: rbac.authorization.k8s.io/v1, Kind=Role" + if deniedByGroup.Content[0].(mcp.TextContent).Text != expectedMessage { + t.Fatalf("expected descriptive error '%s', got %v", expectedMessage, deniedByKind.Content[0].(mcp.TextContent).Text) + } + }) + allowedResource, _ := c.callTool("resources_delete", map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap", "name": "allowed-configmap-to-delete"}) + t.Run("resources_delete (not denied) deletes resource", func(t *testing.T) { + if allowedResource.IsError { + t.Fatalf("call tool should not fail") + } + }) + }) +} diff --git a/pkg 2/mcp/testdata/helm-chart-no-op/Chart.yaml b/pkg 2/mcp/testdata/helm-chart-no-op/Chart.yaml new file mode 100644 index 00000000..de13c067 --- /dev/null +++ b/pkg 2/mcp/testdata/helm-chart-no-op/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v1 +name: no-op +version: 1.33.7 diff --git a/pkg 2/mcp/testdata/helm-chart-secret/Chart.yaml b/pkg 2/mcp/testdata/helm-chart-secret/Chart.yaml new file mode 100644 index 00000000..510edaf0 --- /dev/null +++ b/pkg 2/mcp/testdata/helm-chart-secret/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: secret-chart +version: 0.1.0 +type: application + diff --git a/pkg 2/mcp/testdata/helm-chart-secret/templates/secret.yaml b/pkg 2/mcp/testdata/helm-chart-secret/templates/secret.yaml new file mode 100644 index 00000000..89829fe6 --- /dev/null +++ b/pkg 2/mcp/testdata/helm-chart-secret/templates/secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-secret + labels: + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +type: Opaque +data: + username: {{ b64enc "aitana" }} + password: {{ b64enc "alex" }} + diff --git a/pkg 2/output/output.go b/pkg 2/output/output.go new file mode 100644 index 00000000..c558ae9d --- /dev/null +++ b/pkg 2/output/output.go @@ -0,0 +1,127 @@ +package output + +import ( + "bytes" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" + yml "sigs.k8s.io/yaml" +) + +var Yaml = &yaml{} + +var Table = &table{} + +type Output interface { + // GetName returns the name of the output format, will be used by the CLI to identify the output format. + GetName() string + // AsTable true if the kubernetes request should be made with the `application/json;as=Table;v=0.1` header. + AsTable() bool + // PrintObj prints the given object as a string. + PrintObj(obj runtime.Unstructured) (string, error) +} + +var Outputs = []Output{ + Yaml, + Table, +} + +var Names []string + +func FromString(name string) Output { + for _, output := range Outputs { + if output.GetName() == name { + return output + } + } + return nil +} + +type yaml struct{} + +func (p *yaml) GetName() string { + return "yaml" +} +func (p *yaml) AsTable() bool { + return false +} +func (p *yaml) PrintObj(obj runtime.Unstructured) (string, error) { + return MarshalYaml(obj) +} + +type table struct{} + +func (p *table) GetName() string { + return "table" +} +func (p *table) AsTable() bool { + return true +} +func (p *table) PrintObj(obj runtime.Unstructured) (string, error) { + var objectToPrint runtime.Object = obj + withNamespace := false + if obj.GetObjectKind().GroupVersionKind() == metav1.SchemeGroupVersion.WithKind("Table") { + t := &metav1.Table{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), t); err == nil { + objectToPrint = t + // Process the Raw object to retrieve the complete metadata (see kubectl/pkg/printers/table_printer.go) + for i := range t.Rows { + row := &t.Rows[i] + if row.Object.Raw == nil || row.Object.Object != nil { + continue + } + row.Object.Object, err = runtime.Decode(unstructured.UnstructuredJSONScheme, row.Object.Raw) + // Print namespace if at least one row has it (object is namespaced) + if err == nil && !withNamespace { + switch rowObject := row.Object.Object.(type) { + case *unstructured.Unstructured: + withNamespace = rowObject.GetNamespace() != "" + } + } + } + } + } + buf := new(bytes.Buffer) + // TablePrinter is mutable and not thread-safe, must create a new instance each time. + printer := printers.NewTablePrinter(printers.PrintOptions{ + WithNamespace: withNamespace, + WithKind: true, + Wide: true, + ShowLabels: true, + }) + err := printer.PrintObj(objectToPrint, buf) + return buf.String(), err +} + +func MarshalYaml(v any) (string, error) { + switch t := v.(type) { + //case unstructured.UnstructuredList: + // for i := range t.Items { + // t.Items[i].SetManagedFields(nil) + // } + // v = t.Items + case *unstructured.UnstructuredList: + for i := range t.Items { + t.Items[i].SetManagedFields(nil) + } + v = t.Items + //case unstructured.Unstructured: + // t.SetManagedFields(nil) + case *unstructured.Unstructured: + t.SetManagedFields(nil) + } + ret, err := yml.Marshal(v) + if err != nil { + return "", err + } + return string(ret), nil +} + +func init() { + Names = make([]string, 0) + for _, output := range Outputs { + Names = append(Names, output.GetName()) + } +} diff --git a/pkg 2/output/output_test.go b/pkg 2/output/output_test.go new file mode 100644 index 00000000..ecad73c0 --- /dev/null +++ b/pkg 2/output/output_test.go @@ -0,0 +1,32 @@ +package output + +import ( + "encoding/json" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "regexp" + "testing" +) + +func TestPlainTextUnstructuredList(t *testing.T) { + var podList unstructured.UnstructuredList + _ = json.Unmarshal([]byte(` + { "apiVersion": "v1", "kind": "PodList", "items": [{ + "apiVersion": "v1", "kind": "Pod", + "metadata": { + "name": "pod-1", "namespace": "default", "creationTimestamp": "2023-10-01T00:00:00Z", "labels": { "app": "nginx" } + }, + "spec": { "containers": [{ "name": "container-1", "image": "marcnuri/chuck-norris" }] } } + ]}`), &podList) + out, err := Table.PrintObj(&podList) + t.Run("processes the list", func(t *testing.T) { + if err != nil { + t.Fatalf("Error printing pod list: %v", err) + } + }) + t.Run("prints headers", func(t *testing.T) { + expectedHeaders := "NAME\\s+AGE\\s+LABELS" + if m, e := regexp.MatchString(expectedHeaders, out); !m || e != nil { + t.Errorf("Expected headers '%s' not found in output: %s", expectedHeaders, out) + } + }) +} diff --git a/pkg 2/version/version.go b/pkg 2/version/version.go new file mode 100644 index 00000000..da4ebbd1 --- /dev/null +++ b/pkg 2/version/version.go @@ -0,0 +1,6 @@ +package version + +var CommitHash = "unknown" +var BuildTime = "1970-01-01T00:00:00Z" +var Version = "0.0.0" +var BinaryName = "kubernetes-mcp-server"

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%0D$g=ebVcfjk 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 z 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%0DL5 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 literal 0 HcmV?d00001 diff --git a/docs 2/images/vibe-coding.jpg b/docs 2/images/vibe-coding.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5240edfb873f984c2e0938c07ed8ff9ed1adb751 GIT binary patch literal 194354 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 +L3c7amPLllYH+c#PMm9zX zxk)zgmq2sn-2h7C6u`f7*NuQ#Nysx*$=$B>K{Bmk#&f6xstUhG1 zTS%T(pD5pgYMY(LTT`3N1lo<#I=Gg+N6Ue)9>am=oNS+Gt-mh#oQ)r8k z*Ny>HS$2X%M+2rMNkJ?Ittx8L9ebs9>BwpZiFO5OKBW(kA_P5l^5NlyuG=3M1%?iI z>u|Xldzm#BS|*H$(#KyI8JQkB*cNW>@PeJAmb_cyP>jo$=n4>Y zNr8Z<#O1w^=H+TTuuUcj(tBG%>9?cwx6`ubXxV>G@#$fH56+!{#<^fm(^K%5ckJR! zp7SU;-m?Xf2t^p+#{?b~S$KjpP}(pfD9MJ8bSWU(;Xv#IR!jlO?Mb_YcGD!@U|Ohk zlEX)FKS!XN%#B1Po;~?!b~4V`jvr_n9u*Kf0Xi4x{Kl;L@Lf~#23fzCPBp-c<#Gpy zdZaM-Eq3DMf=%H z+)*JIRYHeBN9j!r(>)A#GlxHKyD~$yHN@7o%2=hxY`I=Ap*UQSpOXYZk_XTCJ#_@( zBp&5L8KVS~xICEkk@Lp(KvLsCM?i-Hy#oG;?+FW^Z_NBYXE-f&>D$0}ik;+6%A;P5 z3k$E@?zCZP`|1cuU3EVVU!&{Uia-^bU3~^b4d7_L@k`OtpeJa*j8I${Gv3g({%o9% z)`BTVDkt&7FyXYpk402L)}zre&m7wzdg`97ULRT7Cr~lTw1TF^z)g`^~_*1#S zz9@=a{Ee_~%5z)nL%PQj6aZjn3#0OP~PBj8z?uS=_OIpAB z*b*MUJc;mqI6OD4`}P-k^?U*9dTFjS*GGqo#Q}I7uix4g2UKDa;lhRc>Hasdno0G? z22KZQR#8#vEi)17c=reE5vUNnJMqzGO^KKFU;%YcDt4FoI1TZ|7#wUou$vZOz_TW= zZv;VM2bh62VtER(ZM;{+x0Q7YkdatA0riZXjiwRPEoa<@MPsB4+cdot@*wF#0e+b6xqEq=4)2r(y+xI? z7x1}K5A!eW-tTkgW&uu5_ue0WNW5vmRPHxtU&Uujs)uXAPq%CQx%6Zw!PDSt)26LW zAM|8W>UAEdMj6wxt7dHF*wg z;_g2!^ZR~`ylg!Lg;I82bLSgay6jmK*x3?{ulg=?oChitQThywv&l7w{4)>){j_e{ zsd5vigWC@-PHSe~*UrCu|2sw=rOCs5@dRE;DWKQ z(B&m9KnPg*?PnX4KY{VOW2=%Y0$n#rvH>~~lJPXRmjwtHY(H#TFEh%wWnx?W0E-S( zHu3i)9YB<72sssDeQQ5FwNNEl#`v2E!gqvcFL!Y^}IhiPs{%P1KW~K zZ|TNs2E7gG;FMU$e34X1mO4)^t<)0XWaYe{-R=kTJR=Ac+8tg;8|fEI@>zpmG8$9t zoF1IzbK2fG?%aS%jgM!}{>gnYUUQh8;#YIZUPe`vxEcmA)~kZ$?ww1>aAnyyzKHHL zyu@UqXgi4@?N(~5;QgWhO^XS|219ksbd~_0L*d=_k&i4YOEdp zl5vuRM7oEuS(P=JxOk+~Mr0e5W`@0Zc&4?YKLfxHAUpk?t$~Ps+!CR`arTAlgXkV ze~7-DbFQG1m_gd-Use+JYjw?3-zUs>TsNvbJDzfnLDvx8*P_GX#}!Gi$T8#H8y88Q&H1!z#b? z%=q{{;2U3k2^{=91z;9{(`izVsZrs@k9^l03nD$g@SBZfbro~0zo@FVTJ*AC2p9`PHF|kKPsZ^ zs5Yn9Aibm`nSMD_m@0p(#MQ;M43DqERxdBF)XlT#miIVOOZg2KNQm{j-LrPwHFnJh zYK*KzHUh8PH7}zj^FRy1J-j?PU_P>-W&oK{6|MHrLgr9NRwd0te^*W>Hh6BB6pg-n zSqs%6le=4rQ5q){OudBDVBKHQBmGEeS4T?sE?U*iXr% zQNhMY#)$7iJ8dc}kU$z~=v(W57g=wBAIgxPTXok%6Az3|MtVeKPMt?xzC50!_PmNU92Y&D{^eNv6}w9r6T|YYvy9nW8Qgbju1y1K8RNj8%REOT-7 zwwUo_+Cj#6m|=62j33Na1-RV6?7$Z1hz?oFU>_R~dkBE-CDBNURd$_*Yeg$y&5P93 z*m%^$@W68hok5c$6%{uSMpLC4JG1k#`&`Q`UPSl(Y^bQq3{IBsrBVtAVP1zU@4i2t zahwT+d50fsP$_zyw+~Xu@(zf>>+iZ)#+~o*;eR@a}S@q9%}5uczvQ}%|@zy`!(vA4()g@ zW6$$0T@Ge?>Nva>*q*alA5*&{`&DQJBS>dzc{Q={(MNh6IFkXVfV_?ZV$!*ZGOsEZ zn5hi}k3I;-zD0e*5?*4?G-dlztBaJsVJBWDH@;#x zsbdhU7;Wm23q2mR0blfOYEf5I?`lU5oxB){=emf;n)fx`m2P z5a!-W-*5()3BKF8jRK|GQEWwR=4E_G{g_+$UGnXGM=^s6LD{vCkF_y*4 z!^;B#Jfd;D(uzAv=kNqT!pq$Eacqc};rzqwK&0=n%NZ_ohGZt)E{(w$M)uZQ)+_fm z?I{NlhAOASD|O^X60>30p$gZCwtmgYxjd{~>_K#^>@fJ&H->SbsbFymQT6+mcO_yj zXNujMK8h!dws!q&Xw}U&Bc+?aXQ+irTEy&EOR`G-Cho3i8kP3x`${JA?Zr zPCuUd6@@J;5+B7A58zYjm4W^`SC~lipKdBhB1PY|EQE5|LUt{Zx-Rb_xZ?WqPO)0+ z7hSjg+Xvda$LgjVvcml}RzAFz@@*o=gP4=Ck?h@sxDvSpIVS)x4?3HjlZN1_eZ#b> zn5K1K8`wAP!%H#Fk#7E6+|F-fY5!T-*hr>~TD-$)ajqzz-HN@GL(U1A(Fj<>j*PBy z#sUqSs!=Y!ZQ-FYoiE+P9#OsytWhE|XZBSMDvmAmMziJKKl+Icr14P-@9cAyRQxbA zwBG)9b#0ktm~GJ8L!aw<8=5UKNO?XkAsM?bQ56=1$hh58*TC@S1mgTZ%&c}k{H0%3 z&^-MsvjoOeSE5Cw7PPwUCCt*ulXJZT~ zUgH=@D#uloF5Ww`p2GPA?GIGGzrA+KxASYz(irU53c{gx&W!4_*=^1ow7!R<5oh-Vd1*JTSzl#^6(7K)PDh0W*U(p12Qh@12kI!| zrpm6$EW)Lw#QkLS_*`Nvbx_iBVE_7B@uO5+pj6hc%KPOt94kiqs87LnY{9v&1D^(o z96Y7ykCX8_2WW4` zCfsg&Ojy;I%^4b!$OEN1*_#|Lx0R?zpz+YA?f97TTOc^Lhvz{sp)+m1LdWu3Tet5A zc#@-yNS;Cx2t7j}`of#CaG&Ko`+S@lr1U&uHCT!|-vY@;Be3_=IqLgef_;WpG$ygk?oiJ9mDt1t;mdCf+h% za=x<}hs^PUiw-&INtf8ev7g|ZmLFOUEeu@zNFg25@rTdN@$ z^VXFH2di&`)B4dK*6!i?>%dcEf2dX$6%hre?{Xg4)eUGN;I_YOVEr~kf!Ft*5q0nB zmr~#5{QZ{$LS2z zfeI`dKQUL8Oh+W{db2>@qp@l@+$dQp+_iLALws~S^HW8IdqHVIX69aZ-Fn9PrIQXr zsX(KbI&qK;(c4c5@){XZs=VmE*{AeE1~HZzvO!DUR!P@ zgGiGxWOOElNL;_QK+W__Z5bRS5UOIGa28J+8ibz%XJ>vkokKYImEq&thZPnsEWRcs zvDhnlEk7FPPWnx8hZ0WMwg}tlV{bLS&tAE`8M7X-fSGe##{K1cb+6E-U825RNQ?p_X?~9aZIx)@kugE|eGNOG+65=ktCtPvF0fci?5PN1_p0)5L zie+%Wn53FcrIOXe+_l8qcW(BNrH5i;${Rj6V>2cESNHz%O{&%tk|sR{`{ zYU!f4eZvYoQsI$%_>{+R$7_o2kw&ifGPlD6sej9e|K8`&rcAEOw*eu_h1~)5p!oyv zfg}jN%UGIM*U~DTF6KcZMAKgZf0R}g-#0cYIf#sJ?`HG`Qsjxkmu7;amv+9Q$LcTO z8wnO0NF7+zjbEe)Q@t9KJhT_evsuVPzvdWJc0ZCl zR-iFUeZb^MuCE3T}E=&bkM-&iH8+G6h7Lhf2Zfkp8M-R15{ zoZFTQ&m-gwoBMl-`*T2^0ag>$J4zL|6HCf1aqbMx|9&DmQ8kzMY@Yq8~;FP`#L1`wk^lZImE=HTJgT)Wqr#_k;S1_OX3OrW7z7S z2}-ra-#@^Q7(VjJdAVTOVbJSZ7G~}IWN22nao~_j^xG6)`6>hrWGw!^Hn*+TyWO~I zWW%EbPZ?oFZ$Hd==wQ2M;NAGLCu&QEOPvnxrGNiiisY}DMLM#18Ta}Y0b#VpNArJQ zqGKtseiCDy(c3ne)shi6xANdDEA~M9;fUbEvoY%W21W;i*A172g^MSu@$Rh-s2g>u ziA+YEhkR!@Q<9<`kXe_W9y1!s9A8+DVa_d$bvy?XecC=YnPJEBX;*#PP6u}yU%0vB z&f0-P(JdxUC|3#=c!-*l8J0w(yI)1!Y(R$iS;l-xRFEGFK{lM%>vg`&81BRlMd(;I zTMafaq8!?>RH@>Er*uHhURt4HfacFMppAA?!D^Qc4K`G_YvqV&kk~pzc~#)vj6ZReNB6#M+IN+BzB* z&O!U$dEc0v*4D!ke!!8$IB0j)TS@s+9mXd@A~i$tG&R3W7i-c15DD>+WaHeb2ez(; zw{Y=kadR@E`{QHwADM~^On{0zNVgTAnj-q@pjEX3(sX(w>#Q^jEJz0BQMXchR>$i0+}?f?{r`tP?3xYVLu~t${isZO@UgtfX|D`zQWlPuvwN;)W;mjX^0=RvozIIU zb}Zbc>W|J+se{>wstI#%UZX?pH%gAs@DG?$$LSl8ac!^9ClKhWuF1@3?HN0AG-AiX zOevDkoM<`sq%&L0k0nP`bJxw5=*JB7s&1<{7(}{H;%^F|17;*!rgV>D@g?{vni5K0e@7o+8}I4xIPp!o@*y3&3n8 z{vJqo3lZCMS8EIHzoaL;oiVsD$e5aCm6UJ8y=vJ%XpLBi=K8oPUF|d7tdfqXK*L+^ z=u2eH#>>PnE7WUQfin?n!c8IeHp2R&3vV)99@Pg-u2wfCbhS3_=VZC>uRdmt#-&Py z4YW=;>)&rrMrl@Hi#{^wpH$qY*b^aTRl2c=C#w~%4V>eP!iI58kxV!-SW&Ul48+qvic6X61)$79_vePY!= zRDxEAGxFL+&Vg)H7cX$O^vDdH!HMiL-&R{Soi)k4-Xd`v`}OUJN)CtFk~MK9>ovuy zYcAFO*T~GkHLBQYem3p-P=vZqtOa3apR<7#8Ee8GeA2FC!>5YHbh57m8O*ftzR5-%FVuZ@&?B=HeKDspPtM_DS{ zrlg0LBHh+3C95XLp`3?jk3YmkrTZ0IK2*D3`7)|f`_S`dznQ?*mV(yrKaVbyRacv1 zZ`p#-PV_3L)6fZ@<8sqU+p#!Auh%Ux`|HS?m3~yC+%R*v+o!HB;Br8*XBWM5B&;N= zUt%VscNieXk@qDl@>)+DCa31~D{x3sj3Yr9#=lcCky`hwa9nh>2kUrq%4?36FB==u0v zo?J@kA%}x#UDNA~eH}~&O1@=HNGmkR=S0V~6TWS8s=}B*8O*l_5CwLvz0)xdANsWW zJ`B+-b4iTxB}$ev95P?KsJN&;Yd3TX69cAj641!QoMGpo!nF>2pBC;s`TQvYzly~z zFMH3;v4-ihO~oKA)Yy4TGM|Jfw+zU}YX-a>?j5ab^a~6};5VR_vVdt}V!@$;_s!!o z^JSWIE|Pj^Ujk6ors1z09P-1<9&AbVP{%Ri{-T%0o6o3d*vK`WYM#5#?3CfVyliCr zAY)84dr5t(-Z362b?7Onuw}{bNM~9I2ccg|N?+0YuvKp;Jh-#85rp^*IKac= z?8m-xBf0|I#qA87CDq6TF7;Ju5**P2f_;*JIy~)Ec1aD_vJI zRR>iKCG(T%mKKKx52o$3+~Me${@G}|EjT1ffC^tkzpb$Yy>p@(Drz#`Fr%{z(^~rs z0wVI)YDm{A8A5 z5^%3Q4oyZ|A9_^BX3^ac_=_Xd**}m$zzs)bOgj}tIvjZZXLcZZe2v*>Rq(vH!H3#7 zTKDa6g#O|>@mjFnns0Gq1JPa2KE3n7rGOycL~D0k*J$kvq%|qW?Bjr%OI~*?4uN3o}C08$!@njrsHJTlr72X1LofMH|aE(kWSS@W2 zs(hG*Z&B&c{~XEeC=CN$QfHYI6MYYT^53$@mb(9T#qh!>NZn>G4P=lcaFdu*-keLa zKauYx>DN5S9;HsKRNQBOo){u{JcPSWl5tseE#kg+X6D`+wM9zF7bLD(MNGt!^lLwbzT6iRMmG4#a z7$f^;(A=!=Y=dsXnl9OB6MF22gK%-y+Kig=d0)ZevFw(U;}?+5VN8^o+7klNxV}*2 zToNzH!VxJ{*yaEJh_$_oic+!ybdl`y(7zR%E*JeYBP!XKF|0cHhr~LW>P26uBniIn zW>-sMw$0O?46*vBEpz-OyQpdXvs|>!y`sLcN2*@pA9j~P)c9?7CeLMz{yJjg?9EB? zils$FQF4byUgcPS8UNv6VL@knY9l^Qk7(T*>6XLj9`#lZc@R9TEm+iAS#|S^5j5$X zsdI=vI8L6)>7>3C8D?Q<#SOLSoS7B+x1egFCjFss9J8{1Ar4jqwxl4nb8oX0C) zv8~zh4ya@RM(1YZ4Td+P#Tgi!Jnhx%9NMYwkDt(&0^f{)F#LO3azN^CkUIl25)`rB z1tJNyAWzRE&K4xyIB&yrtZeScq@yyONpi2=1Exyv=mHA4WPNp%;6Rw_-5ZCc<^Epv zRzHpHC!z{SP*^I{-U;Mf00xk~dnZ7@kNCJmSfj0b$|bu0&4ivyY|eVYp3>J>I5_P5 z1(gtvq05seY1%X&mO3+`dnt#$?|WgRZnhASFxV+iz)vt2@rIth+K)2V+|ds0U8~FO zJ>661zxj?!V)wnmE=M(uuM{{uX!HyCb?9T(!LV{{Mufvnkni6PlC9i;L!ssl5^H!M zZW0SW+VW%FGwC={h3!grciFr#0S~O$f(#Pq>Q~c2wTX&Hmo2wPrHFsSYyGaD+L_o>{}Y@Q*b$p)FHm&uZI zU($JAfJZCRId{2dDK>&<-|U~nB|LVgdaQ!zRz|-NzQ+VOdYaF{f$|;E zduijQkIZ;L&X0{T%wEn`yf+7P+9=4K@?srJ3^z2AfPRb*nx{BiFE;pb$$&Rw^clQFp~ihDUWN(U3%dChSDw7ecB9h0bs z%0R}*bM{KZMzA><_JggTU6;e%4TBuDKtv)q^6hddGGZ^8aE%*VE!_S)ah#%6;ewNPY# zS3V2V>{1K#5Q%ubw|%(e7f2=(Ftt-iJ1=%dM8TwSvH0O_#|d9w!>iVX=_ZPk?H44NTy%#6~VJ7%XQ$_f9Iho@&#yeiGt{o;v zn7g}8^bgwDUhu0JhG>`2YlMcHUboy4H4pWo+KM`lx);}_{qv$d=*@7C~X zR=u6b7q6CriQd2GqlCPe`=J=?2oljye?KXUl7mF{PPzr6%Y17dur*i`mRT2B+P%9C zF!ffcv()isCWvcNNhFH?oAdekoj0d1$GzDlU{af>lu`tq7ZJFsAgyAO0uv}wkgwQN zd4AKj(~%kaFBjFhE7~lQv-`1VKQUkNOPr_T4~7xQzflm$+vO#i=5g8Z&z`H23uzUceDwZMbEeD4iUA^cp@85o7Q-ymPu`7;zpI2$_LasD&2tRj)Fm_ILB($~h^fl;L{1!WSibyVaxJt&H zObXRCtDi-zyI1+VivAhJrytu9@veH`V3yiwXwe4roYw3>jCmP66s~)FR;vG22Ei4v zzv{O2{(M)w7D)IFBqHVKhneo->xdtXANOzXm|tF#nP8Uw0b5f~cx^z>u%u~3PxAH{lyzd}^+gX| zc$5bqR^-|*i_s{9Fnk6QoT_Ql`hWvk)j(MAz3g(g7#@iu9Gsr_+iq?zT?n`3m2-rH z1aljBEeJyA@!IkoB<80FelW=T;Aanl823WCw2;tQ9dL&Dp2?5%^KHfZkeaT8rxo)Q zK<;L>1kxn+6~lLRv9))q-#ubnGq~*S`B-3t2akQCpWZPPjzyP$UW1WwMzwfx-(LMH z^l1$#`U;+xQgGiTnoQ3W)B6>pKeM!NP*@wJOUfU!&eD+b(3T?#PXydG&^~(^Q(ib# z(DuPy*jF{C4{fZMo=*$t?fABrv3J?+c0>R0%9XMG{Tq<>$IPn++VVNi+s88gkPI1_ zcel3SSz;Z1@P^)=^E$FrJGM#BdH>Lt#_PK=zAf1O6D|8b_y@17{u&9>^SFG^1e}1s zeA~Dq?l^!lr$GAQxg?Nc`bf6#&r~gc$g}A7WQI(uCig*QXe(B|-pM5H?7|)W^9YUW zV;a3iGWG`T5Rd2$$=T6mH=tXRi%ElsSrZd4H>wapg zUg%e)?v?)G@B{I6vzQF(AHg~y=Vt|r?+u>(#F7@$60>e;@iQB^k&HZlHdDU01S1YP(PDzS~GtGP4Qny$KKzQWz7V{APqKWTORXSgO6JO-4xSum(lH?w~j z6SwKvr2jhpJgt-Cyyxi{C%pt424ppZQfKctG1YAOdh3tdTYvaWR7*$}#(c=o+0q;E#V=Ov>Ri``-IOYL71BTE@gqngn4$XuiUU-aQJ; zDIPbczu)(4Hpja3Ig9k0Y%x{nM?W6!%T!rIL{2Vify}beqptWP)Je~i7RMGWj;gjr z4V2XH8>Mpgq)PF|YtwIETk>aMv^+Mu>u+{F^mU-YZB3#izjJetFQ1xAMiVD%I>+DT zW|ZzW|CQ5SB`&+qC?!Y(9@z!m0IoL3$ydk)4@jI5fQz0I;}3kgXz51sZ0}|5kJ9dq zcB!sbB~IdF&ZRjiwscK99@V$kZP)bBX`D@KAjC4LE;Yoe=}VyjZbf(YmKD)2t0Bii z`#9@IstaM}0tMknV*}c?{VSGkv?Ft={LxkSL83nV1MK*9l!5=^roGF!+o_e$AGmOw z4=^d2Ul#^)uA$@st?Ku8t??nY-qX95-=h4Z`C+w+a8{+lh~cT=-66m(s6EYDdu_Jq zbR<=(@VlNKf*P-uJYV5hu#lx@LAW>)x@?ZkKnWw&wkN8c829rpQ3pY~BPVDGsSJ`* z0!Zx^1&fDxcoQHy3k4a|!h>i0ASH9pi`>UlOpCwCof|Re`!dSH2@0LxEE29Wc=~?T zf|%>O(J9W@YvXsNf3m{e$CxN#NmlvN@U7PF0rOt0@lxvEXz*-D48KSouYOi}QQh>s z<~R}=<7#!F^FDO^nVbzs$Qkd6Knd!&5%_23k*Ci-(7-(S8p>v$fcX9l;;aX^e*N;OFirU{Cy|}wmiW9uJyA*Gs#pV5O{~wvjWEe>9?w;M8J^TEg z`?e5;d3rE`0sOwh-Z@}8e}~MpUbNs_KEsd}Q!bft?{4gme-~_#Ac^$h*DeUaz!MD& zJNb%!AoTfgH%1oC1b+pi0jCAnrT%T{Tl1P0B~A{%pVra^$c=$hiU7xsQb48&09FIZ z_yDj3D8RtzXyJfvky_j;HL=K&F<9RU9<8B*20+J|0hFa_NQ;%= z^pmxR>y(1ogPzByiCbYC2VDX|;UAzGXNsRZd%?h!AqjeNSS-Eb05a_|C0kEUJVj4z zy49t@tpetXe@zC$@82F9kjwm!{gX@A2BFF0qXh#c9DuGt0ni^gbs$FufvMC`v>1VD z1cwG+^brJz)JG0IB-56zFXBH-4dygjjQ#lY@!BcR1-!acsGabm4(rzv@b(}C3cla_ z^^zdKu8b2iceS+|nPF^eLnQMb2LYVvBplSj9lQwW_YW@$?03_IATCCv! z763*EF{7x=xPT{|T~r6|xL>f5 zKDDM$hC16hIhHWN9y#|fwm#6ZA*0N;Al;%{5g zB*qCPfIwhGQ3sU0=yJgt_^e5GfaV@m$LAt2s}!~hf{QmMqfl;5SoOR