SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

Ni eyikeyi ile-iṣẹ nla, ati X5 Retail Group kii ṣe iyatọ, bi idagbasoke ti nlọsiwaju, nọmba awọn iṣẹ akanṣe ti o nilo aṣẹ olumulo pọ si. Ni akoko pupọ, iyipada ailopin ti awọn olumulo lati ohun elo kan si omiiran ni a nilo ati lẹhinna iwulo wa lati lo olupin Nikan-Sing-On (SSO) kan. Ṣugbọn kini lati ṣe nigbati awọn olupese idanimọ bii AD tabi awọn miiran ti ko ni awọn abuda afikun ti wa ni lilo tẹlẹ ni awọn iṣẹ akanṣe. Kilasi ti awọn ọna ṣiṣe ti a pe ni “awọn alagbata idanimọ” yoo wa si igbala. Iṣẹ julọ julọ ni awọn aṣoju rẹ, gẹgẹbi Keycloak, iṣakoso Wiwọle Gravitee, bbl Ni ọpọlọpọ igba, awọn oju iṣẹlẹ lo le yatọ: ibaraẹnisọrọ ẹrọ, ikopa olumulo, bbl Ojutu gbọdọ ṣe atilẹyin iṣẹ ti o rọ ati iwọn ti o le darapọ gbogbo awọn ibeere ni ọkan, ati iru ojutu kan ti ile-iṣẹ wa ni bayi ni alagbata itọkasi - Keycloak.

SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

Keycloak jẹ idanimọ orisun ṣiṣi ati ọja iṣakoso wiwọle ti a tọju nipasẹ RedHat. O jẹ ipilẹ fun awọn ọja ile-iṣẹ nipa lilo SSO - RH-SSO.

Awọn imọran ipilẹ

Ṣaaju ki o to bẹrẹ lati koju awọn ojutu ati awọn isunmọ, o yẹ ki o pinnu ni awọn ofin ati ọkọọkan awọn ilana:

SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

Idanimọ jẹ ilana fun idanimọ koko-ọrọ nipasẹ idanimọ rẹ (ni awọn ọrọ miiran, eyi ni itumọ orukọ kan, iwọle tabi nọmba).

Ijeri - Eyi jẹ ilana ijẹrisi (olumulo ti ṣayẹwo pẹlu ọrọ igbaniwọle kan, ti ṣayẹwo lẹta naa pẹlu ibuwọlu itanna, bbl)

Aṣẹ - Eyi ni ipese wiwọle si orisun kan (fun apẹẹrẹ, si imeeli).

Identity alagbata Keycloak

Aṣọ bọtini jẹ idanimọ orisun ṣiṣi ati ojutu iṣakoso wiwọle ti a ṣe apẹrẹ fun lilo ni IS nibiti awọn ilana faaji microservice le ṣee lo.

Keycloak nfunni awọn ẹya bii ami-iwọle ẹyọkan (SSO), idanimọ alagbata ati iwọle awujọ, ajọṣepọ olumulo, awọn oluyipada alabara, console abojuto ati console iṣakoso akọọlẹ.

Išẹ ipilẹ ni atilẹyin nipasẹ Keycloak:

  • Wọlé ẹyọkan ati Wọle Ẹyọkan fun awọn ohun elo ẹrọ aṣawakiri.
  • Atilẹyin fun OpenID/OAuth 2.0/SAML.
  • Identity Brokering - ìfàṣẹsí nipa lilo OpenID Sopọ ita tabi awọn olupese idanimọ SAML.
  • Wiwọle Awujọ – atilẹyin fun Google, GitHub, Facebook, Twitter fun idanimọ olumulo.
  • Federation User - mimuuṣiṣẹpọ ti awọn olumulo lati LDAP ati Awọn olupin Itọsọna Active ati awọn olupese idanimo miiran.
  • Afara Kerberos - lilo olupin Kerberos fun ijẹrisi olumulo laifọwọyi.
  • Console Abojuto – fun iṣakoso iṣọkan ti awọn eto ati awọn aṣayan ojutu nipasẹ oju opo wẹẹbu.
  • Console Iṣakoso Account - fun iṣakoso ara ẹni ti profaili olumulo.
  • Isọdi ti ojutu ti o da lori idanimọ ile-iṣẹ ti ile-iṣẹ naa.
  • 2FA Ijeri – Atilẹyin TOTP/HOTP ni lilo Google Authenticator tabi FreeOTP.
  • Awọn ṣiṣan wọle - iforukọsilẹ ti ara ẹni olumulo, imularada ọrọ igbaniwọle ati tunto, ati awọn miiran ṣee ṣe.
  • Isakoso Ikoni - awọn alabojuto le ṣakoso awọn akoko olumulo lati aaye kan.
  • Token Mappers – abuda olumulo abuda, ipa ati awọn miiran ti a beere eroja to àmi.
  • Isakoso eto imulo rọ kọja agbegbe, ohun elo ati awọn olumulo.
  • Atilẹyin CORS - Awọn oluyipada alabara ni atilẹyin CORS ti a ṣe sinu.
  • Awọn atọkun Olupese Iṣẹ (SPI) - Nọmba nla ti awọn SPI ti o gba ọ laaye lati ṣe akanṣe awọn ẹya oriṣiriṣi ti olupin naa: awọn ṣiṣan ijẹrisi, awọn olupese idanimo, aworan ilana ilana, ati diẹ sii.
  • Awọn oluyipada alabara fun awọn ohun elo JavaScript, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Orisun omi.
  • Atilẹyin fun ṣiṣẹ pẹlu awọn ohun elo lọpọlọpọ ti o ṣe atilẹyin ile-ikawe OpenID Connect Relying Party tabi SAML 2.0 Library Olupese Iṣẹ.
  • Expandable lilo awọn afikun.

Fun awọn ilana CI / CD, ati adaṣe ti awọn ilana iṣakoso ni Keycloak, API REST / JAVA le ṣee lo. Awọn iwe aṣẹ wa ni itanna:

REST API https://www.keycloak.org/docs-api/8.0/rest-api/index.html
Java API https://www.keycloak.org/docs-api/8.0/javadocs/index.html

Awọn Olupese Idanimọ Ile-iṣẹ (Lori-Ile)

Agbara lati jẹri awọn olumulo nipasẹ awọn iṣẹ Federation User.

SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

Pass-nipasẹ ìfàṣẹsí tun le ṣee lo - ti awọn olumulo ba jẹri lori awọn ibi iṣẹ pẹlu Kerberos (LDAP tabi AD), lẹhinna wọn le jẹ ifọwọsi laifọwọyi si Keycloak laisi nini lati tẹ orukọ olumulo ati ọrọ igbaniwọle sii lẹẹkansii.

Fun ijẹrisi ati aṣẹ siwaju ti awọn olumulo, o ṣee ṣe lati lo DBMS ibatan, eyiti o wulo julọ fun awọn agbegbe idagbasoke, nitori ko ni awọn eto gigun ati awọn iṣọpọ ni awọn ipele ibẹrẹ ti awọn iṣẹ akanṣe. Nipa aiyipada, Keycloak nlo DBMS ti a ṣe sinu lati tọju awọn eto ati data olumulo.

Atokọ ti awọn DBMS ti o ni atilẹyin jẹ lọpọlọpọ ati pẹlu: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle ati awọn miiran. Awọn idanwo pupọ julọ ni akoko ni Oracle 12C Release1 RAC ati iṣupọ Galera 3.12 fun MariaDB 10.1.19.

Identity olupese - awujo wiwọle

O ṣee ṣe lati lo iwọle lati awọn nẹtiwọọki awujọ. Lati mu agbara ṣiṣẹ lati jẹri awọn olumulo, lo console abojuto Keycloack. Awọn iyipada ninu koodu ohun elo ko nilo ati pe iṣẹ ṣiṣe wa lati inu apoti ati pe o le muu ṣiṣẹ ni eyikeyi ipele ti iṣẹ naa.

SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

O ṣee ṣe lati lo OpenID/SAML Identity awọn olupese fun ijẹrisi olumulo.

Awọn oju iṣẹlẹ aṣẹ aṣoju lilo OAuth2 ni Keycloak

Sisan koodu ašẹ - lo pẹlu olupin-ẹgbẹ awọn ohun elo. Ọkan ninu awọn iru igbanilaaye ti o wọpọ julọ nitori pe o baamu daradara fun awọn ohun elo olupin nibiti koodu orisun ohun elo ati data alabara ko si si awọn ita. Awọn ilana ninu apere yi da lori redirection. Ohun elo naa gbọdọ ni anfani lati ṣe ajọṣepọ pẹlu aṣoju olumulo (olumulo-oluranlọwọ), gẹgẹbi ẹrọ aṣawakiri wẹẹbu kan - lati gba awọn koodu aṣẹ API ti o darí nipasẹ aṣoju olumulo.

Sisan aisọ - ti a lo nipasẹ alagbeka tabi awọn ohun elo wẹẹbu (awọn ohun elo nṣiṣẹ lori ẹrọ olumulo).

Iru igbanilaaye ti ko ṣoki ni lilo nipasẹ alagbeka ati awọn ohun elo wẹẹbu nibiti aṣiri alabara ko le ṣe iṣeduro. Iru igbanilaaye ti ko ṣoki tun nlo atunṣe aṣoju olumulo, nipa eyiti ami iraye si ti kọja si aṣoju olumulo fun lilo siwaju ninu ohun elo naa. Eyi jẹ ki ami naa wa fun olumulo ati awọn ohun elo miiran lori ẹrọ olumulo. Iru igbanilaaye aṣẹ yii ko jẹri idanimọ ohun elo naa, ati pe ilana funrararẹ da lori URL àtúnjúwe (igbasilẹ tẹlẹ pẹlu iṣẹ naa).

Sisan aitọ ko ṣe atilẹyin awọn ami isọdọtun iwọle si.

Sisan Ẹri Onibara - ni lilo nigbati ohun elo ba wọle si API. Iru igbanilaaye aṣẹ yii ni igbagbogbo lo fun awọn ibaraẹnisọrọ olupin-si-olupin ti o gbọdọ ṣe ni abẹlẹ laisi ibaraenisepo olumulo lẹsẹkẹsẹ. Awọn iwe-ẹri alabara funni ni sisan n gba iṣẹ wẹẹbu kan laaye (olubara aṣiri) lati lo awọn iwe-ẹri tirẹ dipo ṣiṣafihan olumulo kan lati jẹri nigbati o n pe iṣẹ wẹẹbu miiran. Fun ipele ti o ga julọ ti aabo, o ṣee ṣe fun iṣẹ pipe lati lo ijẹrisi kan (dipo aṣiri ti o pin) gẹgẹbi iwe-ẹri.

OAuth2 sipesifikesonu jẹ apejuwe ninu
RFC-6749
RFC-8252
RFC-6819

JWT tokini ati awọn anfani rẹ

JWT (JSON Web Token) jẹ apẹrẹ ti o ṣii (https://tools.ietf.org/html/rfc7519) ti o ṣalaye iwapọ ati ọna ti ara ẹni lati gbe alaye labeabo laarin awọn ẹgbẹ bi ohun JSON kan.

Ni ibamu si awọn bošewa, àmi oriširiši meta awọn ẹya ara ni mimọ-64 kika, niya nipa aami. Apa akọkọ ni a pe ni akọsori, eyiti o ni iru ami-ami ati orukọ hash algorithm fun gbigba ibuwọlu oni-nọmba kan. Apa keji tọju alaye ipilẹ (olumulo, awọn abuda, ati bẹbẹ lọ). Apa kẹta ni ibuwọlu oni-nọmba.

. .
Maṣe tọju ami kan ninu DB rẹ rara. Nitoripe ami ti o wulo jẹ deede si ọrọ igbaniwọle kan, titoju ami naa dabi titoju ọrọ igbaniwọle pamọ sinu ọrọ mimọ.
Wiwọle àmi jẹ ami ti o fun oluwa rẹ ni iwọle si awọn orisun olupin to ni aabo. Nigbagbogbo o ni igbesi aye kukuru ati pe o le gbe alaye ni afikun gẹgẹbi adiresi IP ti ẹgbẹ ti n beere fun ami naa.

Sọ àmi jẹ ami ti o fun laaye awọn alabara laaye lati beere awọn ami iraye si tuntun lẹhin igbesi aye wọn ti pari. Awọn ami wọnyi ni a maa n jade fun igba pipẹ.

Awọn anfani akọkọ ti lilo ni faaji microservice:

  • Agbara lati wọle si ọpọlọpọ awọn ohun elo ati awọn iṣẹ nipasẹ ijẹrisi akoko kan.
  • Ni aini ti nọmba kan ti awọn abuda ti a beere ninu profaili olumulo, o ṣee ṣe lati jẹ ọlọrọ pẹlu data ti o le ṣafikun si fifuye isanwo, pẹlu adaṣe ati lori-fly.
  • Ko si iwulo lati tọju alaye nipa awọn akoko ti nṣiṣe lọwọ, ohun elo olupin nikan nilo lati jẹrisi ibuwọlu naa.
  • Iṣakoso iwọle irọrun diẹ sii nipasẹ awọn abuda afikun ninu isanwo isanwo.
  • Lilo ibuwọlu ami kan fun akọsori ati fifuye isanwo n mu aabo ti ojutu naa pọ si lapapọ.

JWT àmi - tiwqn

Akọsori - nipasẹ aiyipada, akọsori ni iru aami nikan ati algorithm ti a lo fun fifi ẹnọ kọ nkan.

Iru aami ti wa ni ipamọ ni bọtini "titẹ". Kọ́kọ́rọ́ 'Irú' náà ni a pa tì nínú JWT. Ti bọtini "titẹ" ba wa, iye rẹ gbọdọ jẹ JWT lati fihan pe nkan yii jẹ Tokini Ayelujara JSON.

Bọtini keji "alg" n ṣalaye algoridimu ti a lo lati encrypt tokini naa. O yẹ ki o ṣeto si HS256 nipasẹ aiyipada. Akọsori ti wa ni koodu ni base64.

{"alg": "HS256", "tẹ": "JWT"}
fifuye (akoonu) - fifuye isanwo tọju alaye eyikeyi ti o nilo lati ṣayẹwo. Bọtini kọọkan ninu fifuye isanwo ni a mọ bi “ipepe”. Fun apẹẹrẹ, o le tẹ ohun elo naa sii nikan nipasẹ ifiwepe (promo pipade). Nígbà tí a bá fẹ́ ké sí ẹnì kan láti kópa, a fi lẹ́tà ìkésíni ránṣẹ́ sí wọn. O ṣe pataki lati ṣayẹwo pe adirẹsi imeeli jẹ ti eniyan ti o gba ifiwepe naa, nitorinaa a yoo fi adirẹsi yii sinu ẹru isanwo, fun eyi a fipamọ sinu bọtini “imeeli”

{"imeeli":"[imeeli ni idaabobo]"}

Awọn bọtini ni fifuye isanwo le jẹ lainidii. Sibẹsibẹ, diẹ wa ni ipamọ:

  • iss (Olufun) - Ṣe idanimọ ohun elo lati eyiti a ti fi ami naa ranṣẹ.
  • iha (Koko-ọrọ) - asọye koko-ọrọ ti aami naa.
  • aud (Awọn olugbo) jẹ ọpọlọpọ awọn gbolohun ọrọ ti o ni imọlara tabi awọn URI ti o jẹ atokọ ti awọn olugba ti ami yii. Nigbati ẹgbẹ gbigba ba gba JWT pẹlu bọtini ti a fun, o gbọdọ ṣayẹwo fun wiwa ararẹ ninu awọn olugba - bibẹẹkọ foju ami naa.
  • exp (Aago Ipari) - Tọkasi nigbati aami ba pari. Iwọn JWT nilo gbogbo awọn imuse rẹ lati kọ awọn ami ti o ti pari. Bọtini exp gbọdọ jẹ aami timestamp ni ọna kika unix.
  • nbf (Ko Ṣaaju) jẹ akoko ni ọna kika unix ti o pinnu akoko nigbati ami naa ba wulo.
  • iat (Ti a gbejade Ni) - Bọtini yii duro fun akoko ti a ṣe ami ami naa ati pe o le ṣee lo lati pinnu ọjọ-ori JWT. Bọtini iat gbọdọ jẹ aami akoko ni ọna kika unix.
  • Jti (ID JWT) - okun kan ti o ṣe asọye idamọ alailẹgbẹ ti ami yii, ti o ni imọlara ọran.

O ṣe pataki lati ni oye pe fifuye isanwo ko ni gbigbe ni fọọmu ti paroko (botilẹjẹpe awọn ami le jẹ itẹ-ẹiyẹ ati lẹhinna o ṣee ṣe lati atagba data ti paroko). Nitorinaa, ko le fipamọ eyikeyi alaye ikoko. Bii akọsori, fifuye isanwo jẹ koodu koodu base64.
Ibuwọlu - nigba ti a ba ni akọle ati isanwo, a le ṣe iṣiro ibuwọlu naa.

Akọsori ati fifuye isanwo ti koodu koodu ni base64 ni a mu ati ni idapo sinu laini ti o yapa nipasẹ aami kan. Okun yii ati bọtini aṣiri lẹhinna jẹ titẹ sii si algorithm fifi ẹnọ kọ nkan ti a sọ pato ninu akọsori (bọtini “alg”). Bọtini le jẹ eyikeyi okun. Awọn okun gigun yoo jẹ ayanfẹ julọ nitori wọn yoo nilo akoko diẹ sii lati yan.

{"alg":"RSA1_5","ẹrù-ẹrù":"A128CBC-HS256"}

Ilé kan Keycloak Failover Cluster faaji

Nigba lilo iṣupọ ẹyọkan fun gbogbo awọn iṣẹ akanṣe, awọn ibeere ti o pọ si wa fun ojutu SSO kan. Nigbati nọmba awọn iṣẹ akanṣe jẹ kekere, awọn ibeere wọnyi ko ṣe akiyesi bẹ fun gbogbo awọn iṣẹ akanṣe, sibẹsibẹ, pẹlu ilosoke ninu nọmba awọn olumulo ati awọn iṣọpọ, awọn ibeere fun wiwa ati alekun iṣẹ.

Awọn eewu ti ikuna ti SSO kan pọ si awọn ibeere fun faaji ojutu ati awọn ọna ti a lo fun apọju ti awọn paati ati pe o yori si SLA ti o muna pupọ. Ni iyi yii, diẹ sii nigbagbogbo lakoko idagbasoke tabi awọn ipele ibẹrẹ ti imuse awọn solusan, awọn iṣẹ akanṣe ni awọn amayederun ifarada ti ara wọn. Bi idagbasoke ti nlọsiwaju, o nilo lati fi awọn aye silẹ fun idagbasoke ati iwọn. Ọna ti o rọ julọ lati kọ iṣupọ ikuna ni lilo agbara agbara eiyan tabi ọna arabara kan.

Lati ṣiṣẹ ni Awọn ipo iṣupọ Nṣiṣẹ/Aṣiṣẹ ati Nṣiṣẹ/Passive, o nilo lati rii daju pe aitasera data ni ibi ipamọ data ibatan kan - awọn apa ibi ipamọ data mejeeji gbọdọ wa ni imuṣiṣẹpọ laarin awọn oriṣiriṣi awọn ile-iṣẹ data pinpin geo-pin.

Apẹẹrẹ ti o rọrun julọ ti fifi sori ẹrọ ifarada-aṣiṣe.

SSO on microservice faaji. A lo Keycloak. Apakan No.. 1

Kini awọn anfani ti lilo iṣupọ ẹyọkan:

  • Ga wiwa ati iṣẹ.
  • Ṣe atilẹyin awọn ipo iṣẹ: Nṣiṣẹ/Nṣiṣẹ, Nṣiṣẹ/Palolo.
  • Agbara lati ṣe iwọn ni agbara - nigba lilo agbara agbara eiyan.
  • O ṣeeṣe ti iṣakoso aarin ati ibojuwo.
  • Ọna iṣọkan fun idanimọ / ijẹrisi / aṣẹ ti awọn olumulo ni awọn iṣẹ akanṣe.
  • Ibaraẹnisọrọ diẹ sii sihin laarin awọn iṣẹ akanṣe laisi ilowosi olumulo.
  • Agbara lati tun lo aami JWT ni awọn iṣẹ akanṣe pupọ.
  • Nikan ojuami ti igbekele.
  • Ifilọlẹ yiyara ti awọn iṣẹ akanṣe nipa lilo awọn iṣẹ microservices/apoti agbara (ko si iwulo lati gbe ati tunto awọn paati afikun).
  • O ṣee ṣe lati ra atilẹyin iṣowo lati ọdọ ataja naa.

Kini Lati Wa Nigbati Eto Iṣiro kan

DBMS

Keycloak nlo eto iṣakoso data data lati fipamọ: awọn ibugbe, awọn alabara, awọn olumulo, ati bẹbẹ lọ.
Iwọn DBMS lọpọlọpọ ni atilẹyin: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak wa pẹlu data data ibatan ti a ṣe sinu tirẹ. A ṣe iṣeduro lati lo fun awọn agbegbe ti kii ṣe fifuye - gẹgẹbi awọn agbegbe idagbasoke.

Lati ṣiṣẹ ni Awọn ipo iṣupọ Nṣiṣẹ/Aṣiṣẹ ati Nṣiṣẹ/Passive, a nilo ibamu data ninu aaye data ibatan, ati awọn apa iṣupọ data mejeeji ni a ṣepọpọ laarin awọn ile-iṣẹ data.

Kaṣe pinpin (Infinspan)

Fun iṣupọ lati ṣiṣẹ bi o ti tọ, imuṣiṣẹpọ afikun ti awọn iru caches wọnyi ni lilo Akoj Data JBoss nilo:

Awọn akoko ìfàṣẹsí – ti a lo lati fi data pamọ nigba ti o ba jẹri olumulo kan pato. Awọn ibeere lati kaṣe yii nigbagbogbo kan ẹrọ aṣawakiri ati olupin Keycloak nikan, kii ṣe ohun elo naa.

Awọn ami iṣe iṣe ni a lo fun awọn oju iṣẹlẹ nibiti olumulo nilo lati jẹrisi iṣe asynchronously (nipasẹ imeeli). Fun apẹẹrẹ, lakoko ṣisan ọrọ igbagbe igbagbe, kaṣe Tokens Infinispan ni a lo lati tọju abala awọn metadata nipa awọn ami iṣe iṣe ti o somọ ti o ti lo tẹlẹ, nitorinaa ko le tun lo.

Caching ati isọdọtun ti data itẹramọṣẹ - ti a lo lati kaṣe data itẹramọṣẹ lati yago fun awọn ibeere ti ko wulo si ibi ipamọ data naa. Nigbati olupin Keycloak eyikeyi ba ṣe imudojuiwọn data naa, gbogbo awọn olupin Keycloak miiran ni gbogbo awọn ile-iṣẹ data nilo lati mọ nipa rẹ.

Iṣẹ - Lo nikan lati firanṣẹ awọn ifiranṣẹ ti ko tọ laarin awọn apa iṣupọ ati awọn ile-iṣẹ data.

Awọn akoko olumulo - ti a lo lati tọju data nipa awọn akoko olumulo ti o wulo fun iye akoko igba ẹrọ aṣawakiri olumulo. Kaṣe naa gbọdọ ṣe ilana awọn ibeere HTTP lati ọdọ olumulo ipari ati ohun elo naa.

Idaabobo agbara Brute - ti a lo lati tọpa data nipa awọn iwọle ti kuna.

Iwontunwonsi fifuye

Iwontunws.funfun fifuye jẹ aaye titẹsi ẹyọkan si ẹṣọ bọtini ati pe o gbọdọ ṣe atilẹyin awọn akoko alalepo.

Awọn olupin ohun elo

Wọn ti lo lati ṣakoso ibaraenisepo ti awọn paati pẹlu ara wọn ati pe o le jẹ agbara tabi fi sinu apoti nipa lilo awọn irinṣẹ adaṣe ti o wa ati igbelowọn agbara ti awọn irinṣẹ adaṣe amayederun. Awọn oju iṣẹlẹ imuṣiṣẹ ti o wọpọ julọ ni OpenShift, Kubernates, Rancher.

Eyi pari apakan akọkọ - imọ-jinlẹ. Ninu jara ti awọn nkan atẹle, awọn apẹẹrẹ ti awọn iṣọpọ pẹlu ọpọlọpọ awọn olupese idanimọ ati awọn apẹẹrẹ awọn eto ni yoo ṣe itupalẹ.

orisun: www.habr.com

Fi ọrọìwòye kun