PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/saltstack/salt/lib/python3.10/site-packages/salt/states
Viewing File: /opt/saltstack/salt/lib/python3.10/site-packages/salt/states/selinux.py
""" Management of SELinux rules =========================== If SELinux is available for the running system, the mode can be managed and booleans can be set. .. code-block:: yaml enforcing: selinux.mode samba_create_home_dirs: selinux.boolean: - value: True - persist: True nginx: selinux.module: - enabled: False .. note:: Use of these states require that the :mod:`selinux <salt.modules.selinux>` execution module is available. """ def __virtual__(): """ Only make this state available if the selinux module is available. """ if "selinux.getenforce" in __salt__: return "selinux" return (False, "selinux module could not be loaded") def _refine_mode(mode): """ Return a mode value that is predictable """ mode = str(mode).lower() if any([mode.startswith("e"), mode == "1", mode == "on"]): return "Enforcing" if any([mode.startswith("p"), mode == "0", mode == "off"]): return "Permissive" if any([mode.startswith("d")]): return "Disabled" return "unknown" def _refine_value(value): """ Return a yes/no value, or None if the input is invalid """ value = str(value).lower() if value in ("1", "on", "yes", "true"): return "on" if value in ("0", "off", "no", "false"): return "off" return None def _refine_module_state(module_state): """ Return a predictable value, or allow us to error out .. versionadded:: 2016.3.0 """ module_state = str(module_state).lower() if module_state in ("1", "on", "yes", "true", "enabled"): return "enabled" if module_state in ("0", "off", "no", "false", "disabled"): return "disabled" return "unknown" def mode(name): """ Verifies the mode SELinux is running in, can be set to enforcing, permissive, or disabled .. note:: A change to or from disabled mode requires a system reboot. You will need to perform this yourself. name The mode to run SELinux in, permissive, enforcing, or disabled. """ ret = {"name": name, "result": False, "comment": "", "changes": {}} tmode = _refine_mode(name) if tmode == "unknown": ret["comment"] = f"{name} is not an accepted mode" return ret # Either the current mode in memory or a non-matching config value # will trigger setenforce mode = __salt__["selinux.getenforce"]() config = __salt__["selinux.getconfig"]() # Just making sure the oldmode reflects the thing that didn't match tmode if mode == tmode and mode != config and tmode != config: mode = config if mode == tmode: ret["result"] = True ret["comment"] = f"SELinux is already in {tmode} mode" return ret # The mode needs to change... if __opts__["test"]: ret["comment"] = f"SELinux mode is set to be changed to {tmode}" ret["result"] = None ret["changes"] = {"old": mode, "new": tmode} return ret oldmode, mode = mode, __salt__["selinux.setenforce"](tmode) if mode == tmode or ( tmode == "Disabled" and __salt__["selinux.getconfig"]() == tmode ): ret["result"] = True ret["comment"] = f"SELinux has been set to {tmode} mode" ret["changes"] = {"old": oldmode, "new": mode} return ret ret["comment"] = f"Failed to set SELinux to {tmode} mode" return ret def boolean(name, value, persist=False): """ Set up an SELinux boolean name The name of the boolean to set value The value to set on the boolean persist Defaults to False, set persist to true to make the boolean apply on a reboot """ ret = {"name": name, "result": True, "comment": "", "changes": {}} bools = __salt__["selinux.list_sebool"]() if name not in bools: ret["comment"] = f"Boolean {name} is not available" ret["result"] = False return ret rvalue = _refine_value(value) if rvalue is None: ret["comment"] = f"{value} is not a valid value for the boolean" ret["result"] = False return ret state = bools[name]["State"] == rvalue default = bools[name]["Default"] == rvalue if persist: if state and default: ret["comment"] = "Boolean is in the correct state" return ret else: if state: ret["comment"] = "Boolean is in the correct state" return ret if __opts__["test"]: ret["result"] = None ret["comment"] = f"Boolean {name} is set to be changed to {rvalue}" return ret ret["result"] = __salt__["selinux.setsebool"](name, rvalue, persist) if ret["result"]: ret["comment"] = f"Boolean {name} has been set to {rvalue}" ret["changes"].update({"State": {"old": bools[name]["State"], "new": rvalue}}) if persist and not default: ret["changes"].update( {"Default": {"old": bools[name]["Default"], "new": rvalue}} ) return ret ret["comment"] = f"Failed to set the boolean {name} to {rvalue}" return ret def module(name, module_state="Enabled", version="any", **opts): """ Enable/Disable and optionally force a specific version for an SELinux module name The name of the module to control module_state Should the module be enabled or disabled? version Defaults to no preference, set to a specified value if required. Currently can only alert if the version is incorrect. install Setting to True installs module source Points to module source file, used only when install is True remove Setting to True removes module .. versionadded:: 2016.3.0 """ ret = {"name": name, "result": True, "comment": "", "changes": {}} if opts.get("install", False) and opts.get("remove", False): ret["result"] = False ret["comment"] = "Cannot install and remove at the same time" return ret if opts.get("install", False): module_path = opts.get("source", name) ret = module_install(module_path) if not ret["result"]: return ret elif opts.get("remove", False): return module_remove(name) modules = __salt__["selinux.list_semod"]() if name not in modules: ret["comment"] = f"Module {name} is not available" ret["result"] = False return ret rmodule_state = _refine_module_state(module_state) if rmodule_state == "unknown": ret["comment"] = "{} is not a valid state for the {} module.".format( module_state, module ) ret["result"] = False return ret if version != "any": installed_version = modules[name]["Version"] if not installed_version == version: ret["comment"] = ( "Module version is {} and does not match " "the desired version of {} or you are " "using semodule >= 2.4".format(installed_version, version) ) ret["result"] = False return ret current_module_state = _refine_module_state(modules[name]["Enabled"]) if rmodule_state == current_module_state: ret["comment"] = f"Module {name} is in the desired state" return ret if __opts__["test"]: ret["result"] = None ret["comment"] = "Module {} is set to be toggled to {}".format( name, module_state ) return ret if __salt__["selinux.setsemod"](name, rmodule_state): ret["comment"] = f"Module {name} has been set to {module_state}" return ret ret["result"] = False ret["comment"] = f"Failed to set the Module {name} to {module_state}" return ret def module_install(name): """ Installs custom SELinux module from given file name Path to file with module to install .. versionadded:: 2016.11.6 """ ret = {"name": name, "result": True, "comment": "", "changes": {}} if __salt__["selinux.install_semod"](name): ret["comment"] = f"Module {name} has been installed" return ret ret["result"] = False ret["comment"] = f"Failed to install module {name}" return ret def module_remove(name): """ Removes SELinux module name The name of the module to remove .. versionadded:: 2016.11.6 """ ret = {"name": name, "result": True, "comment": "", "changes": {}} modules = __salt__["selinux.list_semod"]() if name not in modules: ret["comment"] = f"Module {name} is not available" ret["result"] = False return ret if __salt__["selinux.remove_semod"](name): ret["comment"] = f"Module {name} has been removed" return ret ret["result"] = False ret["comment"] = f"Failed to remove module {name}" return ret def fcontext_policy_present( name, sel_type, filetype="a", sel_user=None, sel_level=None ): """ .. versionadded:: 2017.7.0 Makes sure a SELinux policy for a given filespec (name), filetype and SELinux context type is present. name filespec of the file or directory. Regex syntax is allowed. sel_type SELinux context type. There are many. filetype The SELinux filetype specification. Use one of [a, f, d, c, b, s, l, p]. See also `man semanage-fcontext`. Defaults to 'a' (all files). sel_user The SELinux user. sel_level The SELinux MLS range. """ ret = {"name": name, "result": False, "changes": {}, "comment": ""} new_state = {} old_state = {} filetype_str = __salt__["selinux.filetype_id_to_string"](filetype) current_state = __salt__["selinux.fcontext_get_policy"]( name=name, filetype=filetype, sel_type=sel_type, sel_user=sel_user, sel_level=sel_level, ) if not current_state: new_state = {name: {"filetype": filetype_str, "sel_type": sel_type}} if __opts__["test"]: ret.update({"result": None}) else: add_ret = __salt__["selinux.fcontext_add_policy"]( name=name, filetype=filetype, sel_type=sel_type, sel_user=sel_user, sel_level=sel_level, ) if add_ret["retcode"] != 0: ret.update({"comment": f"Error adding new rule: {add_ret}"}) else: ret.update({"result": True}) else: if current_state["sel_type"] != sel_type: old_state.update({name: {"sel_type": current_state["sel_type"]}}) new_state.update({name: {"sel_type": sel_type}}) else: ret.update( { "result": True, "comment": f'SELinux policy for "{name}" already present ' + 'with specified filetype "{}" and sel_type "{}".'.format( filetype_str, sel_type ), } ) return ret # Removal of current rule is not neccesary, since adding a new rule for the same # filespec and the same filetype automatically overwrites if __opts__["test"]: ret.update({"result": None}) else: change_ret = __salt__["selinux.fcontext_add_policy"]( name=name, filetype=filetype, sel_type=sel_type, sel_user=sel_user, sel_level=sel_level, ) if change_ret["retcode"] != 0: ret.update({"comment": f"Error adding new rule: {change_ret}"}) else: ret.update({"result": True}) if ret["result"] and (new_state or old_state): ret["changes"].update({"old": old_state, "new": new_state}) return ret def fcontext_policy_absent( name, filetype="a", sel_type=None, sel_user=None, sel_level=None ): """ .. versionadded:: 2017.7.0 Makes sure an SELinux file context policy for a given filespec (name), filetype and SELinux context type is absent. name filespec of the file or directory. Regex syntax is allowed. filetype The SELinux filetype specification. Use one of [a, f, d, c, b, s, l, p]. See also `man semanage-fcontext`. Defaults to 'a' (all files). sel_type The SELinux context type. There are many. sel_user The SELinux user. sel_level The SELinux MLS range. """ ret = {"name": name, "result": False, "changes": {}, "comment": ""} new_state = {} old_state = {} current_state = __salt__["selinux.fcontext_get_policy"]( name=name, filetype=filetype, sel_type=sel_type, sel_user=sel_user, sel_level=sel_level, ) if not current_state: ret.update( { "result": True, "comment": f'SELinux policy for "{name}" already absent ' + 'with specified filetype "{}" and sel_type "{}".'.format( filetype, sel_type ), } ) return ret else: old_state.update({name: current_state}) ret["changes"].update({"old": old_state, "new": new_state}) if __opts__["test"]: ret.update({"result": None}) else: remove_ret = __salt__["selinux.fcontext_delete_policy"]( name=name, filetype=filetype, sel_type=sel_type or current_state["sel_type"], sel_user=sel_user, sel_level=sel_level, ) if remove_ret["retcode"] != 0: ret.update({"comment": f"Error removing policy: {remove_ret}"}) else: ret.update({"result": True}) return ret def fcontext_policy_applied(name, recursive=False): """ .. versionadded:: 2017.7.0 Checks and makes sure the SELinux policies for a given filespec are applied. """ ret = {"name": name, "result": False, "changes": {}, "comment": ""} changes_text = __salt__["selinux.fcontext_policy_is_applied"](name, recursive) if changes_text == "": ret.update( { "result": True, "comment": ( 'SElinux policies are already applied for filespec "{}"'.format( name ) ), } ) return ret if __opts__["test"]: ret.update({"result": None}) else: apply_ret = __salt__["selinux.fcontext_apply_policy"](name, recursive) if apply_ret["retcode"] != 0: ret.update({"comment": apply_ret}) else: ret.update({"result": True}) ret.update({"changes": apply_ret.get("changes")}) return ret def port_policy_present(name, sel_type, protocol=None, port=None, sel_range=None): """ .. versionadded:: 2019.2.0 Makes sure an SELinux port policy for a given port, protocol and SELinux context type is present. name The protocol and port spec. Can be formatted as ``(tcp|udp)/(port|port-range)``. sel_type The SELinux Type. protocol The protocol for the port, ``tcp`` or ``udp``. Required if name is not formatted. port The port or port range. Required if name is not formatted. sel_range The SELinux MLS/MCS Security Range. """ ret = {"name": name, "result": False, "changes": {}, "comment": ""} old_state = __salt__["selinux.port_get_policy"]( name=name, sel_type=sel_type, protocol=protocol, port=port, ) if old_state: ret.update( { "result": True, "comment": f'SELinux policy for "{name}" already present ' + 'with specified sel_type "{}", protocol "{}" and port "{}".'.format( sel_type, protocol, port ), } ) return ret if __opts__["test"]: ret.update({"result": None}) else: add_ret = __salt__["selinux.port_add_policy"]( name=name, sel_type=sel_type, protocol=protocol, port=port, sel_range=sel_range, ) if add_ret["retcode"] != 0: ret.update({"comment": f"Error adding new policy: {add_ret}"}) else: ret.update({"result": True}) new_state = __salt__["selinux.port_get_policy"]( name=name, sel_type=sel_type, protocol=protocol, port=port, ) ret["changes"].update({"old": old_state, "new": new_state}) return ret def port_policy_absent(name, sel_type=None, protocol=None, port=None): """ .. versionadded:: 2019.2.0 Makes sure an SELinux port policy for a given port, protocol and SELinux context type is absent. name The protocol and port spec. Can be formatted as ``(tcp|udp)/(port|port-range)``. sel_type The SELinux Type. Optional; can be used in determining if policy is present, ignored by ``semanage port --delete``. protocol The protocol for the port, ``tcp`` or ``udp``. Required if name is not formatted. port The port or port range. Required if name is not formatted. """ ret = {"name": name, "result": False, "changes": {}, "comment": ""} old_state = __salt__["selinux.port_get_policy"]( name=name, sel_type=sel_type, protocol=protocol, port=port, ) if not old_state: ret.update( { "result": True, "comment": f'SELinux policy for "{name}" already absent ' + 'with specified sel_type "{}", protocol "{}" and port "{}".'.format( sel_type, protocol, port ), } ) return ret if __opts__["test"]: ret.update({"result": None}) else: delete_ret = __salt__["selinux.port_delete_policy"]( name=name, protocol=protocol, port=port, ) if delete_ret["retcode"] != 0: ret.update({"comment": f"Error deleting policy: {delete_ret}"}) else: ret.update({"result": True}) new_state = __salt__["selinux.port_get_policy"]( name=name, sel_type=sel_type, protocol=protocol, port=port, ) ret["changes"].update({"old": old_state, "new": new_state}) return ret