{"id":9144,"date":"2026-09-02T11:26:42","date_gmt":"2026-09-02T02:26:42","guid":{"rendered":"https:\/\/hasu0707.duckdns.org\/blog\/?p=9144"},"modified":"2026-09-06T10:55:39","modified_gmt":"2026-09-06T01:55:39","slug":"ldap-%ec%84%9c%eb%b9%84%ec%8a%a4-%ea%b5%ac%ec%b6%95","status":"publish","type":"post","link":"https:\/\/hasu0707.duckdns.org\/blog\/?p=9144","title":{"rendered":"LDAP \uc11c\ube44\uc2a4 \uad6c\ucd95"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><\/div>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><h1>LDAP \uae30\ubcf8 \uc6a9\uc5b4 \ubc0f \ub370\uc774\ud130 \uad6c\uc870<\/h1>\n<h2>\uc6a9\uc5b4 \uc815\ub9ac<\/h2>\n<ul>\n<li>DN (Distinguished Name): \uc5d4\ud2b8\ub9ac\uc758 \uc804\uccb4 \uc808\ub300 \uacbd\ub85c (\uc608: cn=kim,ou=dev,dc=example,dc=com)<\/li>\n<li>RDN (Relative DN): \uc0c1\ub300 \uacbd\ub85c, \ud2b8\ub9ac \uc0c1\uc704 \ub178\ub4dc\uc640 \uad6c\ubd84\ub418\ub294 \uc774\ub984 (\uc608: cn=kim)<\/li>\n<li>dc (Domain Component): \ub3c4\uba54\uc778 \uc694\uc18c (example.com -&gt; dc=example,dc=com)<\/li>\n<li>ou (Organizational Unit): \uadf8\ub8f9\/\ubd80\uc11c \ub2e8\uc704<\/li>\n<li>cn (Common Name): \uac1c\ubcc4 \uac1c\uccb4 \uc774\ub984 (\uc0ac\uc6a9\uc790\uba85, \uc11c\ubc84\uba85 \ub4f1)<\/li>\n<li>sn (Surname): \uc131(Family Name\/Last Name), sn=Hong<\/li>\n<\/ul>\n<pre><code>dc=example,dc=com (\ub3c4\uba54\uc778)\n \u251c\u2500\u2500 ou=dev (\ubd80\uc11c: Organizational Unit)\n \u2502    \u251c\u2500\u2500 cn=kim (\uc0ac\uc6a9\uc790: Common Name)\n \u2502    \u2514\u2500\u2500 cn=lee\n \u2514\u2500\u2500 ou=hr\n      \u2514\u2500\u2500 cn=park\n<\/code><\/pre>\n<ul>\n<li>upn   : User Principal Name ex)\ud638\uc2a4\ud2b8\uba85@\ub3c4\uba54\uc778\uba85<\/li>\n<li>entry : \ub514\ub809\ud130\ub9ac\uc5d0 \ubcf4\uad00\ub41c \uc815\ubcf4\uc758 \uae30\ubcf8 \ub2e8\uc704\ub85c, Entry\uac00 \ub098\ud0c0\ub0b4\ub294 \uac1d\uccb4(\uc0ac\uc6a9\uc790)\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc18d\uc131 \uc9d1\ud569\uc73c\ub85c \uad6c\uc131. Entry\uc758 \uc9d1\ud569\uc740 DN(Distinguished Name)\uc744 \uae30\ubc18\uc73c\ub85c DIT(Directory Information Tree)\ub77c\ub294 \uacc4\uce35\uc801\uc778 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ub428.<\/li>\n<li>ldif  : LDAP Data Interchange Format<\/li>\n<li>l     : LocalityName (\ub3c4\uc2dc, \ud2b9\uc815\uc9c0\uc5ed \ub2e8\uc704\uba85)<\/li>\n<li>c     : Country Name<\/li>\n<li>dit   : Directory Information Tree<\/li>\n<li>ldif  : LDAP Data Interchange Format<\/li>\n<li>o     : Organization Name<\/li>\n<li>uid   : User ID<\/li>\n<li>givenName : \uc774\ub984<\/li>\n<li>Objectclass<\/li>\n<\/ul>\n<blockquote>\n<p>\ubaa8\ub4e0 \uc5d4\ud2b8\ub9ac \ub4e4\uc740 \ud558\ub098\ud558\ub098\uc758 Objectclass \ub97c \uac16\ub294\ub2e4. Objectclass \ub780 \ub3d9\uc77c\ud55c \uc124\uc815\uc744 \uac16\uace0 \uc788\ub294 \uc77c\uc885\uc758 \uadf8\ub8f9\uc774\ub77c\uace0 \uc774\ud574\ud558\uba74 \ub428. \uc0c8\ub85c\uc6b4 \uc5d4\ud2b8\ub9ac\uac00 \uc0dd\uc131\ub420 \ub54c, \ud2b9\uc815\ud55c Objectclass\uc5d0 \uc18d\ud558\ub294 \uc5d4\ud2b8\ub9ac\ub85c \uc0dd\uc131\uc744 \ud558\uac8c \ub418\uba74 \ud574\ub2f9 Objectclass\uc758 \uc18d\uc131\uc744 \uadf8\ub300\ub85c \uc0c1\uc18d\ubc1b\uac8c \ub418\ub294 \uc6d0\ub9ac.\nhttps:\/\/docs.oracle.com\/cd\/E29542_01\/reference.1111\/e10035\/schema_objclass.htm\n\u261e\ucffc\ub9ac\ubb38\uc790\uc5f4 \uc0d8\ud50c (\uc624\ub978\ucabd\uc5d0\uc11c \uc67c\ucabd\uc73c\ub85c \uc77d\ub294\ub2e4)\n\u201ccn=dev-korea,ou=distribution groups,dc=gp,dc=gl,dc=google,dc=com\u201d<\/p>\n<\/blockquote>\n<h2>LDAP \uac1c\ub150 \uc815\ub9ac<\/h2>\n<ul>\n<li>LDAP DIT(Directory Informaation Tree)<\/li>\n<\/ul>\n<pre><code>                   +--------+\n                   |   dc   | dc=com\n                   +---+----+\n                       |\n                   +---+----+\n                   |   dc   | dc=example\n                 +-+--------+--+\n                 |             |\n             +--------+    +--------+\n     ou=tech |   ou   |    |   ou   | ou=sales\n        +----+---+----+    +---+----+----------+\n        |        |             |               |\n  +-------+--+  +--------------+ +----------+ +--+-----------+\n  | cn=staff |  | uid=teseter1 | | cn=staff | | uid=teseter2 |\n  +----------+  +--------------+ +----------+ +--------------+\n  ex) &quot;uid=user01&quot;\uc758 DN\uc740 &quot;uid=user01,ou=tech,dc=example,dc=com&quot;\n      &quot;cn=user01&quot;, &quot;ou=tech&quot; \ub4f1 \ub2e8\uc77c \ud56d\ubaa9\uc740 RDN\n<\/code><\/pre>\n<ul>\n<li>ObjectClass\nEntry\uc5d0\uc11c \uaf2d \ud544\uc694\ud558\uac70\ub098 \uac00\uc9c8 \uc218 \uc788\ub294 Attribute \ud0c0\uc785\uc744 \uc815\uc758\ud55c\ub2e4. Entry\ub97c \ub9cc\ub4e4 \ub54c ObjectClass\ub97c \ud1b5\ud574 \ub370\uc774\ud130\uc5d0 \ud544\uc218\uc801\uc73c\ub85c \ub4e4\uc5b4\uac00\uc57c \ud558\ub294 \uc815\ubcf4\ub97c \ub2f4\uc744 \uc218 \uc788\uac8c \uc815\uc758\ud560 \uc218 \uc788\uc73c\uba70 ObjectClass\ub294 \ub2e4\ub978 ObjectClass\ub97c \uc0c1\uc18d\ud574 \uad6c\ud604\ud558\uba70 \uac1c\ub150\uc744 \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4.<\/li>\n<li>Schema\nSchema\ub294 ObjectClass\uc640 Attribute\uc5d0 \ub300\ud574 \uc815\uc758\ud558\ub294 \uaddc\uce59\uc73c\ub85c \ubcf4\uba74 \ub41c\ub2e4. ObjectClass\uc5d0 \uc5b4\ub5a4 Attribute\uac00 \ub4e4\uc5b4\uac08\uc9c0, Attribute\uc758 \uac12\uc5d0 \ub300\ud55c \uc81c\uc57d \ubc0f \uc870\uac74 \ub4f1 \uad00\ub828\ub41c \uaddc\uce59\ub4e4\uc744 \uc815\uc758\ud560 \uc218 \uc788\ub2e4. \uc2a4\ud0a4\ub9c8 \uc815\uc758\ub97c \ud1b5\ud574 \uc5ec\ub7ec \uc751\uc6a9 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ub514\ub809\ud1a0\ub9ac \uc11c\ube44\uc2a4\ub97c \uc77d\uace0 \uc0ac\uc6a9\ud560 \ub54c \uc0c1\ud638\uc6b4\uc6a9\uc131\uc744 \ubcf4\ud638\ud574\uc8fc\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4.<\/li>\n<li>LDAP \uad6c\uc870\nLDAP\uc740 \uc544\ub798 4\uac00\uc9c0 \ubaa8\ub378\ub85c \ub098\ub20c \uc218 \uc788\ub2e4.\n<ol>\n<li>Information \ubaa8\ub378\n\ub370\uc774\ud130\uc758 \ud615\ud0dc\uc640 \ub370\uc774\ud130\ub97c \ud1b5\ud574 \ub514\ub809\ud1a0\ub9ac \uad6c\uc870\ub85c \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\uc2dd\uc5d0 \uad00\ud55c \uac83\uc73c\ub85c Entry\uc640 \uac01 Entry\ub9c8\ub2e4 Attribute\uac00 \uc874\uc7ac\ud558\uc5ec \ud0c0\uc785\uc774\ub098 \ubcc0\uc218 \uac12\uc744 \uc800\uc7a5\ud560 \uc218 \uc788\ub2e4.\n\u201cOU=People\u201d, &quot;CN=Gerald Carter&quot;\ub4f1\uc740 \ud574\ub2f9 \uacc4\uce35\uc744 \ub098\ud0c0\ub0b4\ub294 \uace0\uc720\ud55c \uc8fc\uc18c Attribute\uc5d0 \ud574\ub2f9\ud55c\ub2e4.<\/li>\n<li>Naming \ubaa8\ub378\n\ud2b8\ub9ac \uad6c\uc870\uc5d0\uc11c \uac01 Entry\ub9c8\ub2e4 \uc874\uc7ac\ud558\ub294 RDN \uac12\ub4e4\uc744 \ud1b5\ud574 \uc6d0\ud558\ub294 \uacbd\ub85c\uc5d0 \uc788\ub294 Entry \uc815\ubcf4\ub97c \ucc3e\uc744 \uc218 \uc788\ub2e4. \ub610\ud55c \uacbd\ub85c \ub0b4 RDN\uac12\ub4e4\uc744 \uc774\uc5b4 \ubd99\uc5ec \uc0dd\uc131\ub41c \uace0\uc720\ud55c \ubb38\uc790\ub97c DN(Distinguished Name)\uc774\ub77c\uace0 \ubd80\ub974\uba70, LDAP\uc758 DIT \ud615\ud0dc\uc5d0\uc11c \uac00\uc7a5 \uc704\uc5d0 \uc874\uc7ac\ud558\ub294 Entry\ub294 DIT\uc758 \uc2dc\uc791\uc810, \ub370\uc774\ud130 \ud2b8\ub9ac\uc758 \ub8e8\ud2b8\ub85c \ubcf4\uba70 \ud558\ub098\uc758 \ub370\uc774\ud130\uc14b\uc73c\ub85c \uc774\ud574\ud560 \uc218 \uc788\ub2e4.<\/li>\n<li>Functional \ubaa8\ub378\nLDAP \ub514\ub809\ud1a0\ub9ac\uc5d0\uc11c \uc791\uc5c5\ud558\ub294 \uba85\ub839\uc744 \uc758\ubbf8\ud55c\ub2e4. 8\uac00\uc9c0\uc758 \uc791\uc5c5 \uba85\ub839\uc73c\ub85c \ub098\ub204\uac8c \ub418\uace0 \uc791\uc5c5 \uba85\ub839\uc758 \uae30\ub2a5\uc5d0 \ub530\ub77c 3\uac00\uc9c0\ub85c \uad6c\ubd84\ud55c\ub2e4.\n<ul>\n<li>\uc9c8\ubb38 \uc791\uc5c5\n<ul>\n<li>Search: \uc8fc\uc5b4\uc9c4 \uc870\uac74\uc5d0 \ub9de\ub294 Entry \ub3c4\ucd9c<\/li>\n<li>Compare: \ud2b9\uc815 Entry\uc758 Attribute \uac12 \ube44\uad50<\/li>\n<\/ul>\n<\/li>\n<li>\uac31\uc2e0 \uc791\uc5c5\n<ul>\n<li>Add: \ub514\ub809\ud1a0\ub9ac\uc5d0 \uc2e0\uaddc Entry \ucd94\uac00<\/li>\n<li>Delete: \ub514\ub809\ud1a0\ub9ac\uc5d0 \uae30\uc874 Entry \uc0ad\uc81c<\/li>\n<li>Modify: \ub514\ub809\ud1a0\ub9ac\uc5d0 \uae30\uc874 Entry \uc218\uc815 \ubc0f Entry DN\uac12 \ubcc0\uacbd<\/li>\n<\/ul>\n<\/li>\n<li>\uc778\uc99d \ubc0f \uc81c\uc5b4 \uc791\uc5c5\n<ul>\n<li>Bind: \ub514\ub809\ud1a0\ub9ac \uc11c\ubc84 \uc5f0\uacb0 \uc2dc \uc0ac\uc6a9\uc790 \uc778\uc99d<\/li>\n<li>Unbind: \ub514\ub809\ud1a0\ub9ac \uc11c\ubc84\uc640\uc758 \uc5f0\uacb0 \ud574\uc81c<\/li>\n<li>Abandon: \uc774\uc804 \uc694\uccad \uba85\ub839\uc744 \ucde8\uc18c<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Security \ubaa8\ub378\n\ub514\ub809\ud1a0\ub9ac\uc5d0 \uc811\uadfc\ud558\ub294 \uc0ac\uc6a9\uc790 \uc778\uc99d\uacfc \ub370\uc774\ud130 \uc811\uadfc \uad8c\ud55c\uc744 \ud1b5\ud574 \uc11c\ube44\uc2a4\ub97c \ubcf4\ud638\ud558\ub294 \ubc29\uc2dd\uc744 \uc758\ubbf8\ud55c\ub2e4. LDAP v3 \ubc84\uc804\uc5d0\uc11c\ub294 \uae30\uc874\uc758 \ubcf4\uc548 \ubc29\uc2dd\ubfd0\ub9cc \uc544\ub2c8\ub77c \uc678\ubd80\uc758 \uc778\uc99d \ubc29\ubc95\uc744 \uc81c\uacf5\ud560 \uc218 \uc788\ub294 SASL \ubc29\uc2dd\ub3c4 \uc81c\uacf5\ud55c\ub2e4.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<hr>\n<h1>OpenLDAP \uc124\uce58 \ubc0f \uc124\uc815<\/h1>\n<h2>OpenLDAP \uc124\uce58<\/h2>\n<pre><code class=\"language-bash\">apt -y install slapd\napt -y install ldap-utils\napt -y install ldap-account-manager\n<\/code><\/pre>\n<h2>OpenLDAP \uae30\ubcf8 \uc124\uc815<\/h2>\n<pre><code class=\"language-bash\">dpkg-reconfigure slapd\n  Omit OpenLDAP server configuration? no\n  DNS domain name: example.com\n  Organization name My Company\n  Administrator password: XXXXXXX\n  Do you want the database to be removed when slapd is purged? no\n  Move old database? yes\nsystemctl status slapd\nsystemctl enable slapd\n<\/code><\/pre>\n<h2>LDAP \uc870\ud68c<\/h2>\n<pre><code class=\"language-bash\">ldapsearch -x -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;dc=example,dc=com&quot;\n<\/code><\/pre>\n<h2>LAM\uc744 \uc704\ud55c PHP LDAP \ud328\ud0a4\uc9c0 \uc124\uce58<\/h2>\n<pre><code class=\"language-bash\">ls -l \/etc\/php \ub85c php \ubc84\uc804 \ud655\uc778 \ud6c4\napt -y install php8.4-ldap\napt -y install php8.4-mbstring\napt -y install php8.4-xml\napt -y install php8.4-curl\napt -y install php8.4-gd\napt -y install php8.4-zip\n<\/code><\/pre>\n<h2>OpenLDAP(slapd) \ub370\uc774\ud130 \ucd08\uae30\ud654<\/h2>\n<p>\ub9cc\uc77c \ub370\uc774\ud130\ub97c \uc644\uc804\ud788 \ucd08\uae30\ud654\ud558\uace0 \ub2e4\uc2dc \uc785\ub825\ud558\ub824\uba74 \uc544\ub798\ub97c \uc785\ub825\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-bash\">systemctl stop slapd\nrm -rf \/var\/lib\/ldap\nrm -rf \/etc\/ldap\/slapd.d\n\ndpkg-reconfigure slapd\nrm -rf \/var\/backups\/*.ldapdb\nsystemctl restart slapd\n<\/code><\/pre>\n<h2>LDAP \uae30\ubcf8 OU \uc0dd\uc131<\/h2>\n<p><code>vi \/root\/scripts\/ldap\/base.ldif<\/code><\/p>\n<pre><code>dn: ou=People,dc=example,dc=com\nobjectClass: organizationalUnit\nou: People\n\ndn: ou=Groups,dc=example,dc=com\nobjectClass: organizationalUnit\nou: Groups\n\ndn: ou=Policies,dc=example,dc=com\nobjectClass: organizationalUnit\nou: Policies\n<\/code><\/pre>\n<ul>\n<li>\ub4f1\ub85d<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">ldapadd -x -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -f \/root\/scripts\/ldap\/base.ldif\n<\/code><\/pre>\n<ul>\n<li>\ud655\uc778<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">ldapsearch -x -H ldap:\/\/10.10.10.1 -b &quot;dc=example,dc=com&quot; &quot;(objectClass=organizationalUnit)&quot;\n<\/code><\/pre>\n<h2>LDAP \uae30\ubcf8 \uadf8\ub8f9 \uc0dd\uc131<\/h2>\n<p><code>vi \/root\/scripts\/ldap\/groups.ldif<\/code><\/p>\n<pre><code>dn: cn=employees,ou=Groups,dc=example,dc=com\nobjectClass: top\nobjectClass: posixGroup\ncn: employees\ngidNumber: 10000\n<\/code><\/pre>\n<ul>\n<li>\ub4f1\ub85d<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">ldapadd -x -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -f \/root\/scripts\/ldap\/groups.ldif\n<\/code><\/pre>\n<h2>LDAP \uc0ac\uc6a9\uc790 \ucd94\uac00 \uc2a4\ud06c\ub9bd\ud2b8 \uc0dd\uc131<\/h2>\n<h3>CSV \ud615\uc2dd\uc758 \uc0ac\uc6a9\uc790 \ub370\uc774\ud130 \uc0dd\uc131<\/h3>\n<pre><code>username,cn,sn,email,password\nuser01,user01,user01,user01@example.com,&quot;Abc!1234#$user01&quot;\nuser02,user02,user02,user02@example.com,&quot;T3st!@#$%^&amp;*02&quot;\nuser03,user03,user03,user03@example.com,&quot;P@ss,w0rd!03&quot;\n...\n<\/code><\/pre>\n<h3>create_ldap_users.sh \uc791\uc131<\/h3>\n<pre><code class=\"language-bash\">#!\/bin\/bash\n\nset -euo pipefail\n\n#-----------------------------------------------------------\n# OpenLDAP CSV bulk user creation script\n#-----------------------------------------------------------\n\nLDAP_URI=&quot;ldap:\/\/10.10.10.1&quot;\n\nBASE_DN=&quot;dc=example,dc=com&quot;\nUSER_BASE_DN=&quot;ou=employees,${BASE_DN}&quot;\nADMIN_DN=&quot;cn=admin,${BASE_DN}&quot;\n\nCSV_FILE=&quot;${1:-users.csv}&quot;\n\nSTART_UID=10000\nGID_NUMBER=10000\n\nWORK_DIR=&quot;\/root\/ldap-user-import&quot;\nLDIF_FILE=&quot;${WORK_DIR}\/users.ldif&quot;\n\n#-----------------------------------------------------------\n# Functions\n#-----------------------------------------------------------\n\ncleanup()\n{\n    unset ADMIN_PASSWORD\n}\n\ntrap cleanup EXIT\n\ndie()\n{\n    echo &quot;ERROR: $*&quot; &gt;&amp;2\n    exit 1\n}\n\n#-----------------------------------------------------------\n# Pre-check\n#-----------------------------------------------------------\n\nif [[ ! -f &quot;${CSV_FILE}&quot; ]]; then\n    die &quot;CSV file not found: ${CSV_FILE}&quot;\nfi\n\ncommand -v ldapadd &gt;\/dev\/null 2&gt;&amp;1 ||\n    die &quot;ldapadd command not found&quot;\n\ncommand -v ldapsearch &gt;\/dev\/null 2&gt;&amp;1 ||\n    die &quot;ldapsearch command not found&quot;\n\ncommand -v python3 &gt;\/dev\/null 2&gt;&amp;1 ||\n    die &quot;python3 command not found&quot;\n\nmkdir -p &quot;${WORK_DIR}&quot;\nchmod 700 &quot;${WORK_DIR}&quot;\n\n: &gt; &quot;${LDIF_FILE}&quot;\nchmod 600 &quot;${LDIF_FILE}&quot;\n\n#-----------------------------------------------------------\n# LDAP administrator password\n#-----------------------------------------------------------\n\nread -r -s -p &quot;LDAP administrator password: &quot; ADMIN_PASSWORD\necho\n\n#-----------------------------------------------------------\n# Test LDAP connection\n#-----------------------------------------------------------\n\necho\necho &quot;[1\/5] Testing LDAP administrator authentication...&quot;\n\nif ! ldapwhoami \\\n    -x \\\n    -H &quot;${LDAP_URI}&quot; \\\n    -D &quot;${ADMIN_DN}&quot; \\\n    -w &quot;${ADMIN_PASSWORD}&quot; \\\n    &gt;\/dev\/null 2&gt;&amp;1\nthen\n    die &quot;LDAP authentication failed&quot;\nfi\n\necho &quot;LDAP authentication: OK&quot;\n\n#-----------------------------------------------------------\n# Check employees OU\n#-----------------------------------------------------------\n\necho\necho &quot;[2\/5] Checking employee OU...&quot;\n\nif ! ldapsearch \\\n    -x \\\n    -H &quot;${LDAP_URI}&quot; \\\n    -D &quot;${ADMIN_DN}&quot; \\\n    -w &quot;${ADMIN_PASSWORD}&quot; \\\n    -b &quot;${USER_BASE_DN}&quot; \\\n    -s base \\\n    &quot;(objectClass=organizationalUnit)&quot; \\\n    dn \\\n    &gt;\/dev\/null 2&gt;&amp;1\nthen\n\n    echo &quot;OU does not exist.&quot;\n    echo &quot;Creating: ${USER_BASE_DN}&quot;\n\n    OU_LDIF=&quot;${WORK_DIR}\/employees-ou.ldif&quot;\n\n    cat &gt; &quot;${OU_LDIF}&quot; &lt;&lt;EOF\ndn: ${USER_BASE_DN}\nobjectClass: top\nobjectClass: organizationalUnit\nou: employees\nEOF\n\n    ldapadd \\\n        -x \\\n        -H &quot;${LDAP_URI}&quot; \\\n        -D &quot;${ADMIN_DN}&quot; \\\n        -w &quot;${ADMIN_PASSWORD}&quot; \\\n        -f &quot;${OU_LDIF}&quot;\nelse\n    echo &quot;OU already exists: ${USER_BASE_DN}&quot;\nfi\n\n#-----------------------------------------------------------\n# CSV -&gt; LDIF\n#-----------------------------------------------------------\n\necho\necho &quot;[3\/5] Converting CSV to LDIF...&quot;\n\npython3 - \\\n    &quot;${CSV_FILE}&quot; \\\n    &quot;${LDIF_FILE}&quot; \\\n    &quot;${USER_BASE_DN}&quot; \\\n    &quot;${START_UID}&quot; \\\n    &quot;${GID_NUMBER}&quot; &lt;&lt;'PYTHON'\nimport base64\nimport csv\nimport hashlib\nimport os\nimport sys\n\ncsv_file = sys.argv[1]\nldif_file = sys.argv[2]\nuser_base_dn = sys.argv[3]\nstart_uid = int(sys.argv[4])\ngid_number = int(sys.argv[5])\n\ndef ssha(password: str) -&gt; str:\n    &quot;&quot;&quot;\n    Generate OpenLDAP-compatible {SSHA} password hash.\n    &quot;&quot;&quot;\n\n    password_bytes = password.encode(&quot;utf-8&quot;)\n\n    salt = os.urandom(8)\n\n    digest = hashlib.sha1(\n        password_bytes + salt\n    ).digest()\n\n    result = digest + salt\n\n    encoded = base64.b64encode(result).decode(&quot;ascii&quot;)\n\n    return &quot;{SSHA}&quot; + encoded\n\ndef ldif_value(value: str) -&gt; str:\n    &quot;&quot;&quot;\n    Encode every attribute value as LDIF Base64.\n\n    This safely handles:\n      - Korean characters\n      - leading\/trailing spaces\n      - colon\n      - hash\n      - quotes\n      - backslashes\n      - special characters\n    &quot;&quot;&quot;\n\n    encoded = base64.b64encode(\n        value.encode(&quot;utf-8&quot;)\n    ).decode(&quot;ascii&quot;)\n\n    return encoded\n\nrequired_fields = {\n    &quot;username&quot;,\n    &quot;cn&quot;,\n    &quot;sn&quot;,\n    &quot;email&quot;,\n    &quot;password&quot;,\n}\n\nwith open(\n    csv_file,\n    &quot;r&quot;,\n    encoding=&quot;utf-8-sig&quot;,\n    newline=&quot;&quot;\n) as f:\n\n    reader = csv.DictReader(f)\n\n    if reader.fieldnames is None:\n        raise SystemExit(&quot;CSV header not found&quot;)\n\n    missing = required_fields - set(reader.fieldnames)\n\n    if missing:\n        raise SystemExit(\n            &quot;Missing CSV fields: &quot;\n            + &quot;, &quot;.join(sorted(missing))\n        )\n\n    rows = list(reader)\n\nif not rows:\n    raise SystemExit(&quot;CSV contains no users&quot;)\n\nusernames = set()\n\nwith open(\n    ldif_file,\n    &quot;w&quot;,\n    encoding=&quot;utf-8&quot;,\n    newline=&quot;\\n&quot;\n) as output:\n\n    for index, row in enumerate(rows):\n\n        username = row[&quot;username&quot;].strip()\n        cn = row[&quot;cn&quot;].strip()\n        sn = row[&quot;sn&quot;].strip()\n        email = row[&quot;email&quot;].strip()\n\n        # Password must NOT be stripped.\n        #\n        # Leading\/trailing spaces may intentionally be part\n        # of the password.\n        password = row[&quot;password&quot;]\n\n        if not username:\n            raise SystemExit(\n                f&quot;Empty username at CSV line {index + 2}&quot;\n            )\n\n        if username in usernames:\n            raise SystemExit(\n                f&quot;Duplicate username: {username}&quot;\n            )\n\n        usernames.add(username)\n\n        if not cn:\n            raise SystemExit(\n                f&quot;Empty cn for user: {username}&quot;\n            )\n\n        if not sn:\n            raise SystemExit(\n                f&quot;Empty sn for user: {username}&quot;\n            )\n\n        if not email:\n            raise SystemExit(\n                f&quot;Empty email for user: {username}&quot;\n            )\n\n        if not password:\n            raise SystemExit(\n                f&quot;Empty password for user: {username}&quot;\n            )\n\n        uid_number = start_uid + index\n\n        password_hash = ssha(password)\n\n        dn = (\n            f&quot;uid={username},&quot;\n            f&quot;{user_base_dn}&quot;\n        )\n\n        home_directory = (\n            f&quot;\/home\/{username}&quot;\n        )\n\n        #\n        # LDIF attributes are Base64 encoded.\n        #\n        # Syntax:\n        #\n        # attribute:: BASE64\n        #\n\n        output.write(\n            f&quot;dn:: {ldif_value(dn)}\\n&quot;\n        )\n\n        output.write(\n            &quot;objectClass: top\\n&quot;\n        )\n\n        output.write(\n            &quot;objectClass: inetOrgPerson\\n&quot;\n        )\n\n        output.write(\n            &quot;objectClass: posixAccount\\n&quot;\n        )\n\n        output.write(\n            &quot;objectClass: shadowAccount\\n&quot;\n        )\n\n        output.write(\n            f&quot;uid:: {ldif_value(username)}\\n&quot;\n        )\n\n        output.write(\n            f&quot;cn:: {ldif_value(cn)}\\n&quot;\n        )\n\n        output.write(\n            f&quot;sn:: {ldif_value(sn)}\\n&quot;\n        )\n\n        output.write(\n            f&quot;mail:: {ldif_value(email)}\\n&quot;\n        )\n\n        output.write(\n            f&quot;uidNumber: {uid_number}\\n&quot;\n        )\n\n        output.write(\n            f&quot;gidNumber: {gid_number}\\n&quot;\n        )\n\n        output.write(\n            f&quot;homeDirectory:: &quot;\n            f&quot;{ldif_value(home_directory)}\\n&quot;\n        )\n\n        output.write(\n            &quot;loginShell: \/bin\/bash\\n&quot;\n        )\n\n        output.write(\n            f&quot;userPassword:: &quot;\n            f&quot;{ldif_value(password_hash)}\\n&quot;\n        )\n\n        output.write(&quot;\\n&quot;)\n\n        print(\n            f&quot;{username}: &quot;\n            f&quot;uidNumber={uid_number}&quot;\n        )\n\nprint()\nprint(\n    f&quot;Generated {len(rows)} LDAP users&quot;\n)\nPYTHON\n\n#-----------------------------------------------------------\n# Check duplicate LDAP users\n#-----------------------------------------------------------\n\necho\necho &quot;[4\/5] Checking existing LDAP users...&quot;\n\nEXISTING_USER=0\n\nwhile IFS= read -r USERNAME\ndo\n    [[ -z &quot;${USERNAME}&quot; ]] &amp;&amp; continue\n\n    RESULT=$(\n        ldapsearch \\\n            -x \\\n            -LLL \\\n            -H &quot;${LDAP_URI}&quot; \\\n            -D &quot;${ADMIN_DN}&quot; \\\n            -w &quot;${ADMIN_PASSWORD}&quot; \\\n            -b &quot;${USER_BASE_DN}&quot; \\\n            &quot;(uid=${USERNAME})&quot; \\\n            dn \\\n            2&gt;\/dev\/null || true\n    )\n\n    if [[ -n &quot;${RESULT}&quot; ]]; then\n        echo &quot;Already exists: ${USERNAME}&quot;\n        EXISTING_USER=1\n    fi\n\ndone &lt; &lt;(\n    python3 - &quot;${CSV_FILE}&quot; &lt;&lt;'PYTHON'\nimport csv\nimport sys\n\nwith open(\n    sys.argv[1],\n    &quot;r&quot;,\n    encoding=&quot;utf-8-sig&quot;,\n    newline=&quot;&quot;\n) as f:\n    reader = csv.DictReader(f)\n\n    for row in reader:\n        print(row[&quot;username&quot;].strip())\nPYTHON\n)\n\nif [[ &quot;${EXISTING_USER}&quot; -ne 0 ]]; then\n    die &quot;Existing LDAP users detected. Import cancelled.&quot;\nfi\n\n#-----------------------------------------------------------\n# LDAP import\n#-----------------------------------------------------------\n\necho\necho &quot;[5\/5] Adding users to LDAP...&quot;\n\nldapadd \\\n    -x \\\n    -H &quot;${LDAP_URI}&quot; \\\n    -D &quot;${ADMIN_DN}&quot; \\\n    -w &quot;${ADMIN_PASSWORD}&quot; \\\n    -f &quot;${LDIF_FILE}&quot;\n\necho\necho &quot;==================================================&quot;\necho &quot;LDAP user import completed&quot;\necho &quot;==================================================&quot;\necho\necho &quot;CSV:&quot;\necho &quot;  ${CSV_FILE}&quot;\necho\necho &quot;Base DN:&quot;\necho &quot;  ${USER_BASE_DN}&quot;\necho\necho &quot;UID range:&quot;\necho &quot;  ${START_UID} - $((START_UID + 11))&quot;\necho\necho &quot;Generated LDIF:&quot;\necho &quot;  ${LDIF_FILE}&quot;\necho\n<\/code><\/pre>\n<h2>create_ldap_users.sh \uc2e4\ud589<\/h2>\n<pre><code class=\"language-bash\">.\/create_ldap_users.sh \/root\/scripts\/ldap\/ldap_users.csv\nLDAP administrator password:\n...\nGenerated LDIF:\n  \/root\/ldap-user-import\/users.ldif\n<\/code><\/pre>\n<h2>\uacc4\uc815 \uc815\uc0c1 \ub4f1\ub85d \ud655\uc778<\/h2>\n<pre><code class=\"language-bash\">ldapsearch -x -LLL -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;ou=employees,dc=example,dc=com&quot; &quot;(objectClass=posixAccount)&quot; dn uid\n<\/code><\/pre>\n<h2>\uc218\ub3d9 \ucd94\uac00 (\uc624\ub958 \ubc1c\uc0dd \uc2dc)<\/h2>\n<pre><code class=\"language-bash\">ldapadd -x -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -v -f \/root\/ldap-user-import\/users.ldif\n<\/code><\/pre>\n<hr>\n<h1>OpenLDAP(slapd) \uc778\uc99d\uc11c \uc801\uc6a9<\/h1>\n<h2>OpenLDAP(slapd) \uc778\uc99d\uc11c \uc0dd\uc131<\/h2>\n<pre><code class=\"language-bash\">mkdir \/etc\/ssl\/ldap\n<\/code><\/pre>\n<h3>CA (\uc778\uc99d \uae30\uad00) \uc778\uc99d\uc11c \uc0dd\uc131<\/h3>\n<ol>\n<li>CA \uac1c\uc778\ud0a4 \uc0dd\uc131<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">openssl genrsa -out \/etc\/ssl\/ldap\/ca.key 4096\n<\/code><\/pre>\n<ol start=\"2\">\n<li>CA \uc778\uc99d\uc11c \uc0dd\uc131 (\uc720\ud6a8\uae30\uac04 10\ub144)<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">openssl req -new -x509 -days 3650 -key \/etc\/ssl\/ldap\/ca.key -out \/etc\/ssl\/ldap\/ca.crt -subj &quot;\/C=KR\/ST=Seoul\/L=Seoul\/O=example\/OU=IT\/CN=exampleCA&quot;\n<\/code><\/pre>\n<h3>SAN (Subject Alternative Name) \ud655\uc7a5 \uc791\uc131<\/h3>\n<pre><code class=\"language-bash\">cat &gt; \/etc\/ssl\/ldap\/san.ext &lt;&lt; EOF\nsubjectAltName = @alt_names\n[alt_names]\nDNS.1 = ldap.example.com\nIP.1 = 10.10.10.1\nEOF\n<\/code><\/pre>\n<hr>\n<h3>LDAP \uc11c\ubc84 \uc778\uc99d\uc11c \uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">openssl genrsa -out \/etc\/ssl\/ldap\/ldap.example.com.key 4096\nopenssl req -new -key \/etc\/ssl\/ldap\/ldap.example.com.key -out \/etc\/ssl\/ldap\/ldap.example.com.csr -subj &quot;\/C=KR\/ST=Seoul\/L=Seoul\/O=example\/OU=IT\/CN=ldap.example.com&quot;\n<\/code><\/pre>\n<h3>CA\ub85c \uc11c\ubc84 \uc778\uc99d\uc11c \uc11c\uba85<\/h3>\n<pre><code class=\"language-bash\">openssl x509 -req -in \/etc\/ssl\/ldap\/ldap.example.com.csr -CA \/etc\/ssl\/ldap\/ca.crt -CAkey \/etc\/ssl\/ldap\/ca.key -CAcreateserial -out \/etc\/ssl\/ldap\/ldap.example.com.crt -days 3650 -sha256 -extfile \/etc\/ssl\/ldap\/san.ext\n<\/code><\/pre>\n<h3>LDAP \uc11c\ubc84 \uc778\uc99d\uc11c \uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">openssl verify -CAfile \/etc\/ssl\/ldap\/ca.crt \/etc\/ssl\/ldap\/ldap.example.com.crt\n\/etc\/ssl\/ldap\/ldap.example.com.crt: OK\n<\/code><\/pre>\n<h3>LDAP \uc778\uc99d\uc11c \uc801\uc6a9<\/h3>\n<pre><code class=\"language-bash\">chown root:openldap \/etc\/ssl\/ldap\/ldap.example.com.key\nchmod 640 \/etc\/ssl\/ldap\/ldap.example.com.key\nvi \/root\/scripts\/ldap\/ldap-tls.ldif\n<\/code><\/pre>\n<pre><code>dn: cn=config\nchangetype: modify\nreplace: olcTLSCertificateFile\nolcTLSCertificateFile: \/etc\/ssl\/ldap\/ldap.example.com.crt\n-\nreplace: olcTLSCertificateKeyFile\nolcTLSCertificateKeyFile: \/etc\/ssl\/ldap\/ldap.example.com.key\n-\nreplace: olcTLSCACertificateFile\nolcTLSCACertificateFile: \/etc\/ssl\/ldap\/ca.crt\n<\/code><\/pre>\n<pre><code class=\"language-bash\">ldapmodify -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/scripts\/ldap\/ldap-tls.ldif\n<\/code><\/pre>\n<h3>LDAP \uc778\uc99d\uc11c \uac80\uc0ac \ube44\ud65c\uc131\ud654 (\uc0ac\uc124 \uc778\uc99d\uc11c\uc778 \uacbd\uc6b0\uc5d0 \uc801\uc6a9)<\/h3>\n<pre><code class=\"language-bash\">vi \/etc\/ldap\/ldap.conf\n<\/code><\/pre>\n<pre><code>TLS_CACERT \/etc\/ssl\/ldap\/ca.crt\nTLS_REQCERT demand\n#TLS_REQCERT never\n<\/code><\/pre>\n<p>\ucd94\uac00<\/p>\n<h3>LDAP \uc778\uc99d\uc11c \ud65c\uc131\ud654<\/h3>\n<pre><code class=\"language-bash\">vi \/etc\/default\/slapd\n<\/code><\/pre>\n<pre><code>\uc544\ub798\ub97c \uc218\uc815\ud55c\ub2e4.\nSLAPD_SERVICES=&quot;ldap:\/\/\/ ldapi:\/\/\/&quot; \u2192\nSLAPD_SERVICES=&quot;ldap:\/\/\/ ldapi:\/\/\/ ldaps:\/\/\/&quot;\nsystemctl restart slapd\n# \ud655\uc778\nss -lntp | grep slapd\nLISTEN ... :636\nLISTEN ... :389\n<\/code><\/pre>\n<h3>TLS \ud655\uc778<\/h3>\n<pre><code class=\"language-bash\">openssl s_client -connect 127.0.0.1:636 -servername ldap.example.com\n<\/code><\/pre>\n<h3>LDAP \ud655\uc778<\/h3>\n<pre><code class=\"language-bash\">ldapsearch -x -H ldaps:\/\/ldap.example.com:636 -b &quot;dc=example,dc=com&quot;\n<\/code><\/pre>\n<h3>Password Policy \uc124\uc815<\/h3>\n<h4>Password Policy \ubaa8\ub4c8 \ucd94\uac00<\/h4>\n<pre><code class=\"language-bash\">vi \/root\/scripts\/ldap\/ppolicy-module.ldif\n<\/code><\/pre>\n<pre><code>dn: cn=module{0},cn=config\nchangetype: modify\nadd: olcModuleLoad\nolcModuleLoad: ppolicy.la\n<\/code><\/pre>\n<p>ldapmodify -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/scripts\/ldap\/ppolicy-module.ldif<\/p>\n<h2>Password Policy \ubaa8\ub4c8 \ud655\uc778<\/h2>\n<p>ldapsearch -Y EXTERNAL -H ldapi:\/\/\/ -b cn=config \u2018(objectClass=olcModuleList)\u2019 olcModuleLoad\nolcModuleLoad: {1}ppolicy.la<\/p>\n<h2>Password Policy entry \uc0dd\uc131<\/h2>\n<p>\ucd5c\uc18c \uae38\uc774       10\n\uc774\uc804 PW \uc7ac\uc0ac\uc6a9  \ucd5c\uadfc 2\uac1c \uae08\uc9c0\n\uc2e4\ud328 \ud5c8\uc6a9       5\ud68c\n\uc7a0\uae08 \uc2dc\uac04       15\ubd84\nPW \ub9cc\ub8cc         \uc5c6\uc74c\n\uc0ac\uc6a9\uc790 PW \ubcc0\uacbd  \ud5c8\uc6a9<\/p>\n<p>vi \/root\/scripts\/ldap\/password-policy.ldif<\/p>\n<pre><code>dn: cn=default,ou=Policies,dc=example,dc=com\ncn: default\nobjectClass: pwdPolicy\nobjectClass: namedPolicy\nobjectClass: top\npwdAllowUserChange: TRUE\npwdAttribute: userPassword\npwdCheckQuality: 1\npwdExpireWarning: 0\npwdFailureCountInterval: 900\npwdGraceAuthNLimit: 0\npwdInHistory: 2\npwdLockout: TRUE\npwdLockoutDuration: 900\npwdMaxAge: 0\npwdMaxFailure: 5\npwdMinAge: 0\npwdMinLength: 10\npwdMustChange: FALSE\npwdSafeModify: TRUE\n<\/code><\/pre>\n<pre><code class=\"language-bash\">ldapadd -Y EXTERNAL -H ldapi:\/\/\/ -f \/etc\/ldap\/schema\/namedobject.ldif\nldapadd -x -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -f \/root\/scripts\/ldap\/password-policy.ldif\n<\/code><\/pre>\n<h4>ppolicy overlay \uc801\uc6a9<\/h4>\n<p>ppolicy overlay\ub294 \ub514\ub809\ud1a0\ub9ac \ub0b4\ubd80\uc5d0\uc11c \uc9c1\uc811 \uc11c\ubc84 \uce21 \ube44\ubc00\ubc88\ud638 \uc815\ucc45\uc744 \uad00\ub9ac\ud560 \uc218 \uc788\uac8c \ud574\uc8fc\ub294 \ud575\uc2ec \ubaa8\ub4c8. \uc774\ub294 LDAP \ud074\ub77c\uc774\uc5b8\ud2b8\ub098 \ubcc4\ub3c4\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, OpenLDAP \uc11c\ubc84 \uc790\uccb4\uc5d0\uc11c \ube44\ubc00\ubc88\ud638\uc758 \ubcf5\uc7a1\uc131, \ub9cc\ub8cc, \uc7a0\uae08 \ub4f1\uc758 \uaddc\uce59\uc744 \uc801\uc6a9\ud558\uace0 \uad00\ub9ac.<\/p>\n<ul>\n<li>\n<p>OpenLDAP database \ubc88\ud638 \ucc3e\uae30\nldapsearch -Y EXTERNAL -H ldapi:\/\/\/ -b cn=config \u2018(olcSuffix=dc=example,dc=com)\u2019 dn olcSuffix\n\u201cdn: olcDatabase={1}mdb,cn=config\u201d \uc874\uc7ac\ub97c \ud655\uc778\ud55c\ub2e4.<\/p>\n<\/li>\n<li>\n<p>\ub4f1\ub85d<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">vi \/root\/scripts\/ldap\/ppolicy-overlay.ldif\n<\/code><\/pre>\n<pre><code>dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config\nobjectClass: olcOverlayConfig\nobjectClass: olcPPolicyConfig\nolcOverlay: ppolicy\nolcPPolicyDefault: cn=default,ou=Policies,dc=example,dc=com\nolcPPolicyHashCleartext: TRUE\n<\/code><\/pre>\n<pre><code class=\"language-bash\">ldapadd -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/scripts\/ldap\/ppolicy-overlay.ldif\n<\/code><\/pre>\n<ul>\n<li>\ud655\uc778<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">ldapsearch -Y EXTERNAL -H ldapi:\/\/\/ -b cn=config '(olcOverlay=ppolicy)'\nppolicy_hash_cleartext\ub97c \uc0ac\uc6a9\ud558\uba74 LDAP \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 password modify \uc694\uccad\uc744 \ubcf4\ub0bc \ub54c \uc11c\ubc84\uac00 \uc11c\ubc84 \uce21 password hashing \uc815\ucc45\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4. \uc774 \uacbd\uc6b0 \uc804\uc1a1 \uad6c\uac04\uc744 \ubc18\ub4dc\uc2dc TLS\ub85c \ubcf4\ud638\ud574\uc57c \ud55c\ub2e4.\n<\/code><\/pre>\n<hr>\n<h1>LAM(LDAP Account Manager) Community<\/h1>\n<h2>LDAP Account Manager \uc124\uce58<\/h2>\n<pre><code class=\"language-bash\">cd \/opt\nwget https:\/\/github.com\/LDAPAccountManager\/lam\/releases\/download\/9.6\/ldap-account-manager-9.6.tar.bz2\ntar -xjf ldap-account-manager-9.6.tar.bz2\nrm -f ldap-account-manager-9.6.tar.bz2\nln -s ldap-account-manager-9.6 ldap-account-manager\n<\/code><\/pre>\n<h2>LDAP Account Manager \ud37c\ubbf8\uc158 \uc870\uc815<\/h2>\n<pre><code class=\"language-bash\">cd \/opt\/ldap-account-manager\ncp config\/config.cfg.sample config\/config.cfg\nchown -R root:root \/opt\/ldap-account-manager\nchown -R www-data:www-data \\\n  \/opt\/ldap-account-manager\/sess \\\n  \/opt\/ldap-account-manager\/tmp \\\n  \/opt\/ldap-account-manager\/config\nfind \/opt\/ldap-account-manager\/sess \\\n     \/opt\/ldap-account-manager\/tmp \\\n     \/opt\/ldap-account-manager\/config \\\n     -type d -exec chmod 750 {} \\;\nfind \/opt\/ldap-account-manager\/sess \\\n     \/opt\/ldap-account-manager\/tmp \\\n     \/opt\/ldap-account-manager\/config \\\n     -type f -exec chmod 640 {} \\;\nchmod 750 \/opt\/ldap-account-manager\/lib\/lamdaemon.pl\n<\/code><\/pre>\n<hr>\n<h1>LDAP Tool Box Self Service Password \uc124\uce58 \uc900\ube44<\/h1>\n<h2>\uc124\uce58<\/h2>\n<pre><code class=\"language-bash\">apt install -y \\\n php8.4 \\\n php8.4-cli \\\n php8.4-common \\\n php8.4-curl \\\n php8.4-gd \\\n php8.4-ldap \\\n php8.4-mbstring \\\n php8.4-xml \\\n smarty4 \\\n curl \\\n ca-certificates\n<\/code><\/pre>\n<h2>LDAP Tool Box Self Service Password \uc124\uce58<\/h2>\n<pre><code class=\"language-bash\">cd \/opt\nwget https:\/\/ltb-project.org\/archives\/ltb-project-self-service-password-1.8.1.tar.gz\ntar -xzf ltb-project-self-service-password-1.8.1.tar.gz\nrm -f ltb-project-self-service-password-1.8.1.tar.gz\nchown -R root:root ltb-project-self-service-password-1.8.1\nln -s ltb-project-self-service-password-1.8.1 self-service-password\n<\/code><\/pre>\n<h2>LDAP Tool Box Self Service Password \ud37c\ubbf8\uc158 \uc870\uc815<\/h2>\n<pre><code class=\"language-bash\">cd \/opt\/self-service-password\nmkdir -p \/opt\/self-service-password\/cache\nmkdir -p \/opt\/self-service-password\/templates_c\nchown -R root:root \/opt\/self-service-password\nchown www-data:www-data \\\n  \/opt\/self-service-password\/cache \\\n  \/opt\/self-service-password\/templates_c\nchmod 750 \\\n  \/opt\/self-service-password\/cache \\\n  \/opt\/self-service-password\/templates_c\n<\/code><\/pre>\n<h2>LDAP Tool Box Self Service Password \uc124\uc815 \ud30c\uc77c \uc218\uc815<\/h2>\n<pre><code class=\"language-bash\">cp \/opt\/self-service-password\/conf\/config.inc.php \/opt\/self-service-password\/conf\/config.inc.php.orig\nvi \/opt\/self-service-password\/conf\/config.inc.local.php\n<\/code><\/pre>\n<pre><code class=\"language-php\">&lt;?php\n\/*\n * ============================================================\n * Debug\n * ============================================================\n *\/\n$debug = false;\n\n\/*\n * ============================================================\n * LDAP\n * ============================================================\n *\/\n$ldap_type = &quot;openldap&quot;;\n$ldap_url = &quot;ldaps:\/\/ldap.example.com:636&quot;;\n$ldap_starttls = false;\n$ldap_base = &quot;ou=employees,dc=example,dc=com&quot;;\n$ldap_login_attribute = &quot;uid&quot;;\n$ldap_fullname_attribute = &quot;cn&quot;;\n$ldap_scope = &quot;sub&quot;;\n$ldap_filter = &quot;(&amp;(objectClass=inetOrgPerson)(objectClass=posixAccount)(uid={login}))&quot;;\n$ldap_network_timeout = 10;\n\n\/*\n * ============================================================\n * LDAP manager account\n * ============================================================\n *\/\n$ldap_binddn = &quot;cn=admin,dc=example,dc=com&quot;;\n$ldap_bindpw = &quot;LDAP \ud328\uc2a4\uc6cc\ub4dc&quot;;\n\n\/*\n * ============================================================\n * Password change\n * ============================================================\n *\/\n$who_change_password = &quot;user&quot;;\n$ldap_use_exop_passwd = true;\n$ldap_use_ppolicy_control = true;\n\n\/*\n * ============================================================\n * Password policy\n * ============================================================\n *\/\n$pwd_min_length = 10;\n$pwd_max_length = 0;\n$pwd_min_lower = 1;\n$pwd_min_upper = 1;\n$pwd_min_digit = 1;\n$pwd_min_special = 1;\n$pwd_special_chars = &quot;^a-zA-Z0-9&quot;;\n$pwd_diff_login = true;\n$pwd_forbidden_ldap_fields = array(\n    &quot;uid&quot;,\n    &quot;cn&quot;,\n    &quot;sn&quot;,\n    &quot;mail&quot;\n);\n$pwd_complexity = 0;\n$pwd_show_policy = &quot;always&quot;;\n$pwd_show_policy_pos = &quot;above&quot;;\n$pwd_display_entropy = true;\n$pwd_check_entropy = false;\n\n\/*\n * ============================================================\n * Features\n * ============================================================\n *\/\n$use_change = true;\n$use_questions = false;\n$use_tokens = false;\n$use_sms = false;\n$use_restapi = false;\n$use_attributes = false;\n# openssl rand -base64 48\n$keyphrase = &quot;YMYG7xwwElJir52QrXjfuWZwcSLVNIlQGE1ySSoI20ppPIn4MZxNoBid9M36oXyY&quot;;\n\n\/*\n * ============================================================\n * General\n * ============================================================\n *\/\n$reset_url = &quot;https:\/\/www.example.com\/ssp\/&quot;;\n$lang = &quot;ko&quot;;\n$allowed_lang = array(\n    &quot;ko&quot;,\n    &quot;en&quot;\n);\n\n$date_timezone = &quot;Asia\/Seoul&quot;;\n$show_menu = true;\n$show_help = true;\n$default_action = &quot;change&quot;;\n$use_captcha = false;\n\n\/*\n * ============================================================\n * Production\n * ============================================================\n *\/\n$show_extended_error = false;\n$smarty_debug = false;\n\n\/*\n * ============================================================\n * Smarty\n * ============================================================\n *\/\nif (!defined(&quot;SMARTY&quot;)) {\n    define(&quot;SMARTY&quot;, &quot;\/usr\/share\/php\/smarty4\/Smarty.class.php&quot;);\n}\n<\/code><\/pre>\n<pre><code class=\"language-bash\">chown -R root:www-data \/opt\/self-service-password\/conf\nchmod 750 \/opt\/self-service-password\/conf\nchmod 640 \/opt\/self-service-password\/conf\/*\n<\/code><\/pre>\n<hr>\n<h2>\uacc4\uc815 \uc874\uc7ac \uc5ec\ubd80 \uac80\uc0ac<\/h2>\n<pre><code class=\"language-bash\">ldapsearch -x -LLL -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;ou=employees,dc=example,dc=com&quot; &quot;(objectClass=posixAccount)&quot; dn uid\n<\/code><\/pre>\n<h2>\uc0ac\uc6a9\uc790\uac00 \ud604\uc7ac \ube44\ubc00\ubc88\ud638\ub85c Bind \uac00\ub2a5\ud55c\uc9c0 \ud655\uc778<\/h2>\n<pre><code class=\"language-bash\">ldapwhoami -x -H ldaps:\/\/ldap.example.com:636 -D &quot;uid=user01,ou=employees,dc=example,dc=com&quot; -W\ndn:uid=user01,ou=employees,dc=example,dc=com\n<\/code><\/pre>\n<h2>\uc790\uae30 \ube44\ubc00\ubc88\ud638 \ubcc0\uacbd\uc774 \uac00\ub2a5\ud55c\uc9c0 \ud655\uc778<\/h2>\n<pre><code class=\"language-bash\">ldappasswd -x -H ldaps:\/\/ldap.example.com:636 -D &quot;uid=user01,ou=employees,dc=example,dc=com&quot; -w 'Pass@234' -S\n<\/code><\/pre>\n<h2>apache \uc124\uc815<\/h2>\n<pre><code class=\"language-bash\">mkdir -p \/etc\/apache2\/includes\nvi \/etc\/apache2\/includes\/example-ldap-tools.conf\n<\/code><\/pre>\n<pre><code class=\"language-nginx\"># ============================================================\n# LDAP Web Management Tools\n#\n# Include this file INSIDE the existing www.example.com:443\n# VirtualHost.\n#\n# LAM:\n#   https:\/\/www.example.com\/lam\/\n#\n# Self Service Password:\n#   https:\/\/www.example.com\/ssp\/\n# ============================================================\n\n# ------------------------------------------------------------\n# LDAP Account Manager\n# ------------------------------------------------------------\nRedirectMatch 301 ^\/lam$ \/lam\/\nAlias \/lam\/ \/opt\/ldap-account-manager\/\n\n&lt;Directory \/opt\/ldap-account-manager&gt;\n  Options -Indexes\n  AllowOverride None\n  Require all granted\n  DirectoryIndex index.html index.php\n\n  &lt;FilesMatch &quot;(^\\.|\\.bak$|\\.old$|\\.orig$|~$)&quot;&gt;\n    Require all denied\n  &lt;\/FilesMatch&gt;\n&lt;\/Directory&gt;\n\n# LAM runtime\/configuration data must never be downloaded directly.\n&lt;Directory \/opt\/ldap-account-manager\/config&gt;\n  Require all denied\n&lt;\/Directory&gt;\n\n&lt;Directory \/opt\/ldap-account-manager\/sess&gt;\n  Require all denied\n&lt;\/Directory&gt;\n\n&lt;Directory \/opt\/ldap-account-manager\/tmp&gt;\n  Require all denied\n&lt;\/Directory&gt;\n\n# ------------------------------------------------------------\n# Self Service Password\n# ------------------------------------------------------------\nRedirectMatch 301 ^\/ssp$ \/ssp\/\nAlias \/ssp\/ \/opt\/self-service-password\/htdocs\/\n&lt;Directory \/opt\/self-service-password\/htdocs&gt;\n  Options -Indexes\n  AllowOverride None\n  Require all granted\n  DirectoryIndex index.php\n  AddDefaultCharset UTF-8\n\n  &lt;FilesMatch &quot;(^\\.|\\.bak$|\\.old$|\\.orig$|~$)&quot;&gt;\n    Require all denied\n  &lt;\/FilesMatch&gt;\n&lt;\/Directory&gt;\n\n# ------------------------------------------------------------\n# SSP REST API\n# ------------------------------------------------------------\n# SSP documentation recommends denying REST by default.\n# The current deployment does not use REST.\nAlias \/ssp\/rest\/ \/opt\/self-service-password\/rest\/\n&lt;Directory \/opt\/self-service-password\/rest&gt;\n  Options -Indexes\n  AllowOverride None\n  Require all denied\n&lt;\/Directory&gt;\n<\/code><\/pre>\n<h3>apache \ud65c\uc131\ud654<\/h3>\n<ul>\n<li>https:\/\/www.example.com\/lam<\/li>\n<li>https:\/\/www.example.com\/ssp<\/li>\n<\/ul>\n<h3>\uc0ac\uc804 LDAP \ud2b8\ub9ac \uac80\uc0c9 (\ub370\uc774\ud130 \ud655\uc778)<\/h3>\n<pre><code class=\"language-bash\">ldapsearch -LLL -x -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;dc=example,dc=com&quot; dn\ndn: dc=example,dc=com\ndn: ou=People,dc=example,dc=com\ndn: ou=Groups,dc=example,dc=com\ndn: ou=Policies,dc=example,dc=com\ndn: cn=employees,ou=Groups,dc=example,dc=com\ndn: cn=default,ou=Policies,dc=example,dc=com\ndn: ou=employees,dc=example,dc=com\n\nldapsearch -LLL -x -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;dc=example,dc=com&quot; -s one &quot;(objectClass=organizationalUnit)&quot; dn\ndn: ou=People,dc=example,dc=com\ndn: ou=Groups,dc=example,dc=com\ndn: ou=Policies,dc=example,dc=com\ndn: ou=employees,dc=example,dc=com\n\nldapsearch -LLL -x -H ldaps:\/\/ldap.example.com:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;ou=employees,dc=example,dc=com&quot; &quot;(uid=user01)&quot; objectClass\n<\/code><\/pre>\n<h2>LAM Community \uae30\ubcf8 \uc124\uc815<\/h2>\n<h3>Server Profile \uc124\uc815<\/h3>\n<ul>\n<li>\n<p>LAM configuration &gt; Edit general settings<\/p>\n<\/li>\n<li>\n<p>Configuration storage<\/p>\n<ul>\n<li>Database type: Local file system<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Security settings<\/p>\n<ul>\n<li>Hide LDAP details on failed login: \u2611<\/li>\n<li>Allowed hosts:\n<ul>\n<li>121.170.221.42<\/li>\n<li>119.196.53.221<\/li>\n<li>59.15.104.62<\/li>\n<li>10.10.10.*<\/li>\n<li>127.0.0.1<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Password policy<\/p>\n<ul>\n<li>Minimum password length: 10\n\u2026<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Server Profile \ucd94\uac00<\/h2>\n<ul>\n<li>LAM configuration &gt; Edit server profiles &gt; Manage server profiles<\/li>\n<li>Add profile\n<ul>\n<li>Profile name: example<\/li>\n<li>Profile password \/ Reenter password \uc785\ub825<\/li>\n<li>Template: unix<\/li>\n<li>[Add]<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Server Profile \uc124\uc815<\/h2>\n<ul>\n<li>\n<p>LAM configuration &gt; profile name: example &gt; Edit server profiles<\/p>\n<\/li>\n<li>\n<p>General settings<\/p>\n<ul>\n<li>Server settings\n<ul>\n<li>Server address: ldaps:\/\/ldap.example.com:636<\/li>\n<li>Activate TLS: no<\/li>\n<li>Login method: Fixed list<\/li>\n<li>List of valid users: cn=admin,dc=example,dc=com<\/li>\n<li>Advanced options+\n<ul>\n<li>Display name: example<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Language settings\n<ul>\n<li>Default language: English (USA)<\/li>\n<li>Time zone: Asia\/Seoul<\/li>\n<\/ul>\n<\/li>\n<li>Tool settings\n<ul>\n<li>Tree suffix: dc=example,dc=com<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Account types<\/p>\n<ul>\n<li>Active account types\n<ul>\n<li>Users\n<ul>\n<li>LDAP suffix: ou=employees,dc=example,dc=com<\/li>\n<li>List attributes: #uid;#cn;#sn;#mail;#uidNumber;#gidNumber<\/li>\n<\/ul>\n<\/li>\n<li>Groups\n<ul>\n<li>LDAP suffix: ou=groups,dc=example,dc=com<\/li>\n<li>List attributes: #cn;#gidNumber;#memberUID;#description<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Module settings<\/p>\n<ul>\n<li>Unix\n<ul>\n<li>Options\n<ul>\n<li>Password hash type: SSHA<\/li>\n<li>Login shells: \/usr\/sbin\/nologin \ucd94\uac00<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>OpenLDAP \ud328\uc2a4\uc6cc\ub4dc \ubcc0\uacbd<\/h2>\n<ul>\n<li>MDB database\uc758 olcRootPW\ub97c \ubcc0\uacbd<\/li>\n<\/ul>\n<h2>\ube44\ubc00\ubc88\ud638 \ud574\uc26c \uc0dd\uc131<\/h2>\n<pre><code class=\"language-bash\">slappasswd\nNew password: XXXXXXXXXXXX\nRe-enter new password: XXXXXXXXXXXX\n{SSHA}...\n<\/code><\/pre>\n<h2>\uc2e4\uc81c LDAP database DN \ud655\uc778<\/h2>\n<pre><code class=\"language-bash\">ldapsearch -Y EXTERNAL -H ldapi:\/\/\/ -LLL -b cn=config '(olcSuffix=dc=example,dc=com)' dn olcRootDN olcRootPW\ndn: olcDatabase={1}mdb,cn=config \ud655\uc778\n<\/code><\/pre>\n<h2>olcRootPW \ubcc0\uacbd<\/h2>\n<pre><code class=\"language-bash\">cat &gt; \/root\/scripts\/ldap\/change-ldap-admin-password.ldif &lt;&lt;'EOF'\ndn: olcDatabase={1}mdb,cn=config\nchangetype: modify\nreplace: olcRootPW\nolcRootPW: {SSHA}...\uc744 \uc785\ub825\nEOF\n<\/code><\/pre>\n<h2>\uc801\uc6a9<\/h2>\n<pre><code class=\"language-bash\">ldapmodify -Y EXTERNAL -H ldapi:\/\/\/ -f \/root\/scripts\/ldap\/change-ldap-admin-password.ldif\n<\/code><\/pre>\n<hr>\n<h1>\uc790\uc8fc \uc0ac\uc6a9\ud558\ub294 LDAP \uad00\ub9ac \ucee4\ub9e8\ub4dc<\/h1>\n<hr>\n<h2>\uc77c\ubc18 \uc0ac\uc6a9\uc790\uc758 \ud328\uc2a4\uc6cc\ub4dc \ubcc0\uacbd<\/h2>\n<pre><code class=\"language-bash\">ldappasswd -x -H ldaps:\/\/ldap.example.com:636 -D &quot;uid=user01,ou=employees,dc=example,dc=com&quot; -w 'Pass@234' -S\n<\/code><\/pre>\n<hr>\n<h2>OpenLDAP \uc0ac\uc6a9\uc790 \ucd94\uac00<\/h2>\n<h3>\ube44\ubc00\ubc88\ud638 \ud574\uc26c \uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">slappasswd\nNew password: XXXXXXXXXXXX\nRe-enter new password: XXXXXXXXXXXX\n{SSHA}...\n<\/code><\/pre>\n<h3>uidNumber \uc911\ubcf5 \uac80\uc0ac<\/h3>\n<ul>\n<li>\u26a0\uc911\uc694: uidNumber: 10020\ub294 \uc808\ub300 \uc911\ubcf5\ub418\uba74 \uc548\ub418\uba70, \uc544\ub798\uc758 \ucee4\ub9e8\ub4dc\ub85c \ubbf8\ub9ac \uac80\uc0ac\ud55c\ub2e4. (\uc544\ubb34\uac83\ub3c4 \uc548\ub098\uc624\uba74 \uc131\uacf5)<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">ldapsearch -x -LLL -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;ou=employees,dc=example,dc=com&quot; &quot;(uidNumber=10020)&quot; dn\n<\/code><\/pre>\n<h3>\ubaa8\ub4e0 \uc0ac\uc6a9\uc790 \ubaa9\ub85d \ucd9c\ub825<\/h3>\n<pre><code class=\"language-bash\">ldapsearch -x -LLL -H ldap:\/\/10.10.10.1 -b &quot;ou=employees,dc=example,dc=com&quot; uidNumber\n<\/code><\/pre>\n<h3>LDIF \uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">vi \/root\/testuser.ldif\n<\/code><\/pre>\n<pre><code>dn: uid=testuser,ou=employees,dc=example,dc=com\nobjectClass: top\nobjectClass: inetOrgPerson\nobjectClass: posixAccount\nobjectClass: shadowAccount\nuid: testuser\ncn: \ud64d\uae38\ub3d9\nsn: testuser\nmail: testuser@example.com\nuidNumber: 10020\ngidNumber: 10000\nhomeDirectory: \/home\/testuser\nloginShell: \/bin\/bash\nuserPassword: {SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxx\n<\/code><\/pre>\n<h3>\uc0dd\uc131<\/h3>\n<pre><code class=\"language-bash\">ldapadd -x -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -f \/root\/testuser.ldif\n<\/code><\/pre>\n<h3>\uc0dd\uc131 \ud655\uc778<\/h3>\n<pre><code class=\"language-bash\">ldapsearch -x -LLL -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;ou=employees,dc=example,dc=com&quot; &quot;(uid=testuser)&quot;\n<\/code><\/pre>\n<hr>\n<h2>OpenLDAP \uc0ac\uc6a9\uc790 \uc0ad\uc81c<\/h2>\n<pre><code class=\"language-bash\">ldapdelete -H ldap:\/\/10.10.10.1 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' &quot;uid=user01,ou=employees,dc=example,dc=com&quot;\n<\/code><\/pre>\n<hr>\n<h2>OpenLDAP \uc5f0\uacb0 \ud14c\uc2a4\ud2b8<\/h2>\n<pre><code class=\"language-bash\">export LDAPTLS_REQCERT=never\nldapsearch -LLL -x -H ldaps:\/\/10.10.10.1:636 -D &quot;cn=admin,dc=example,dc=com&quot; -w 'Pass@234' -b &quot;dc=example,dc=com&quot; dn\n<\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[39],"tags":[],"class_list":["post-9144","post","type-post","status-publish","format-standard","hentry","category-os_linux_unix_macos"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/9144","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9144"}],"version-history":[{"count":0,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/9144\/revisions"}],"wp:attachment":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}