Apache Basic Authentication via LDAP

Punyapat Sessomboon
6 min readApr 7, 2020

--

ตามชื่อหัวข้อเลย เราจะมาทำ Basic Authen ผ่าน LDAP กัน โดยตัวอย่างในวันนี้จะใช้ Web Server เป็น Apache เพราะว่ามี Native Support โดยตัว LDAP Server ที่จะใช้วันนี้คือ ApacheDS

สำหรับ Nginx จะเป็นบทความต่อไป จะต้องพลิกแพลงนิดหน่อย แต่ก็ใช้งานได้

สำหรับใครที่ยังไม่ได้อ่านบทความก่อนหน้า แนะนำให้อ่านและลองทำให้คล่องก่อน เพราะว่าหลายๆ ขั้นตอนในบทความนี้จะไม่ได้อธิบายอย่างละเอียดเพราะอธิบายในบทความก่อนหน้าแล้ว

มาเริ่มกันเลยย

  1. ติดตั้ง LDAP Server ให้เรียบร้อย ตรวจสอบว่าเชื่อมต่อกับ Apache Directory Studio ได้ (ถ้าใช้งาน Production อย่าลืมเปลี่ยน password admin ด้วย) ถ้าใครใช้ docker ก็อย่าลืม Bind Data Directory ออกมาไว้ข้างนอกด้วย ไม่งั้นเดี๋ยว Start Container ใหม่ข้อมูลที่ Config ไว้จะหายไป ตัวอย่างเช่น
    docker run -d -p 389:10389 -v /home/perth/apacheds_data/:/var/lib/apacheds openmicroscopy/apacheds

2. สร้าง Partition ใหม่ ในตัวอย่างนี้เราจะใช้ชื่อว่า dc=insightera,dc=co,dc=th

หน้าจอตัวอย่างตอนสร้าง partition ใหม่

3. สร้าง organizationUnit 2 ตัวใต้ dc=insightera,dc=co,dc=th โดยตั้งชื่อว่า ou=staff และ ou=config

สร้าง ou ใหม่ 2 ตัว

4. สร้าง person ใต้ ou=config โดยตั้งชื่อว่า cn=binding จะเป็น User ที่ใช้สำหรับการทำ binding (บางที่จะเรียกว่า reader) เท่านั้น โดย User นี้จะมีสิทธิ์แค่อ่านข้อมูลบางอย่างของ user อื่นๆ ในระบบ เฉพาะที่จำเป็นต่อการ Authentication และ Authorization เช่น Hashed Password, Group Member แต่ยังไงก็แล้วแต่ user นี้ก็คือเป็นความลับต้องไม่ให้คนทั่วไปรู้ username/password

สร้าง binding user

5. สร้าง person 2 คน โดยตั้งชื่อว่า cn=nareerat.s และ cn=punyapat.s โดย cn นี้จะเป็น Username ที่ใช้ในการทำ Basic Authen และจะต้องเป็น Unique ด้วย

สร้าง user จริงในระบบ

6. ตั้ง Password ให้ทั้ง 2 person ที่เพิ่งสร้างใหม่ โดยในตัวอย่างนี้จะตั้ง Password เป็น “secret” ทั้ง 2 คน

ตั้ง password ด้วย attribute userPassword

7. สร้าง Group ของ person โดยใช้ Entry ที่ชื่อว่า groupOfUniqueNames และใส่ DN ของ punyapat.s เข้าไป (DN ไม่ต้องพิมพ์เองก็ได้ สามารถคลิกขวาที่ Entry punyapat.s แล้วเลือก Copy Entry / DN)

สร้าง Entry ใหม่

ตั้งชื่อว่า cn=general หมายถึง staff ทุกคนในทีม

ตั้งชื่อ group นี้ว่า general

ใส่ DN ของ punyapat.s

เนื่องจากเป็น attribute บังคับ จึงต้องใส่ค่าอย่างน้อย 1 ค่าก่อน

เมื่อเสร็จแล้วจะได้ตามภาพ

เพิ่ม Entry ใหม่ชื่อว่า cn=general พร้อม member 1 คนคือ punyapat.s

8. หลังจากนั้นก็เพิ่ม cn=nareerat.s เข้าไปด้วย เพราะว่าเป็น Group General เลยต้องมีพนักงานทุกคน

เพิ่ม nareerat.s เข้าไปใช้ group general

9. สร้าง Group ใหม่ ชื่อว่า cn=manager และ เพิ่ม nareerat.s แค่คนเดียว โดยทำเหมือนขั้นตอนในข้อ 8 เลย

สร้าง group ใหม่ชื่อ manager และเพิ่ม member แค่ nareerat.s

เท่านี้ก็เรียบร้อย สำหรับฝั่ง LDAP Server สรุปสิ่งที่เราทำไปคือ

  • เราสร้าง User สำหรับ binding (cn=binding)
  • เราสร้าง User จริง 2 คน (cn=punyapat.s, cn=nareerat.s)
  • เราสร้าง Group 2 อัน (cn=general, cn=manager) โดยมี nareerat.s อยู่ทั้ง 2 Groups และ punyapat.s อยู่แค่ Group General

Apache server configuration

ต่อไปเราก็จะมาดูฝั่งของ Apache โดยเราจะสร้าง Directory ขึ้นมา 2 อัน คือ general_data และ manager_data โดย User ที่อยู่ใน Group General จะดูได้เฉพาะ Folder general_data และ User ที่อยู่ใน group manager ก็จะดูได้เฉพาะ Folder manager_data

  1. ตั้งค่าให้ Apache Allow Override ผ่าน .htaccess โดยถ้าใช้ Ubuntu ก็จะต้องแก้ไฟล์ /etc/apache/apache.conf โดยแก้ Directory /var/www ให้ AllowOverride เป็น All (Default เป็น None)
แก้ AllowOverride ของ /var/www/ เป็น All

2. Enable Apache Module ที่ชื่อว่า mod_authnz_ldap ด้วยสำสั่ง

sudo a2enmod authnz_ldap
sudo service apache2 restart

3. ไปสร้าง Folder general_data และ manager_data ไว้ที่ /var/www/html/ แล้วข้างในก็ใส่ index.html ง่ายๆ ไว้

โคงสร้าง file ใน /var/www/html

ถ้าทดลองเข้าเว็บตอนนี้เลยก็จะเห็น

URL และ result ของ general_data
URL และ result ของ general_data

4. ต่อไปเราจะสร้าง .htaccess ไฟล์ใน general_data กัน และจำกำหนดให้ User ที่จะเข้ามาดู Folder นี้ได้ ต้องอยู่ใน Group general เท่านั้น

AuthType Basic
AuthName "Secure Area"
AuthBasicProvider ldap
AuthLDAPURL ldap://localhost:389/dc=insightera,dc=co,dc=th?cn
AuthLDAPBindDN cn=binding,ou=config,dc=insightera,dc=co,dc=th
AuthLDAPBindPassword password
Require ldap-group cn=general,dc=insightera,dc=co,dc=th
  • AuthBasicProvider บอกว่าเราต้องการ Authen ด้วย LDAP
  • AuthLDAPURL คือ URL ของ LDAP Server และ Scope ของ DN ที่เราต้องการไปค้น (Base DN) และ ?cn คือค่าที่เราต้องการเอามาเปรียบเทียบกับ Username (ซึ่งในตัวอย่างนี้คือ cn และอีก ttribute ที่ใช้กันเยอะคือ uid)
  • AuthLDAPBindDN และ AuthLDAPBindPassword คือ Account ที่ใช้ในการ Bind และ Search หา Username ที่ได้รับมา ถ้าไม่ใส่ 2 ค่านี้ Client จะพยายาม Binding แบบ Anonymous Access ซึ่งปกติเราควรจะปิดไว้เพื่อป้องกันข้อมูลรั่วไหล
  • Require ldap-group เป็นการบอกว่า เราจะให้เฉพาะคนที่อยู่ใน List ของ Group นี้เท่านั้นที่สามารถดูข้อมูลของ Folder นี้ได้
ภาพตัวอย่างการแก้ไฟล์ .htaccess

5. เมื่อทดลองเข้าหน้าเว็บก็จะพบกับกล่อง Basic Authen

basic authen

ถ้าใส่ Password ถูกก็จะสามารถเข้าไปดูข้างใน Folder ได้ ทั้ง cn=punyapat.s และ cn=nareerat

6. ทำขั้นตอนที่ 4 อีกรอบ แต่สร้าง .htaccess ใน manager_data และจำกัดสิทธิ์เฉพาะ User ใน Group manager

AuthType Basic
AuthName "Secure Area"
AuthBasicProvider ldap
AuthLDAPURL ldap://localhost:389/dc=insightera,dc=co,dc=th?cn
AuthLDAPBindDN cn=binding,ou=config,dc=insightera,dc=co,dc=th
AuthLDAPBindPassword password
Require ldap-group cn=manager,dc=insightera,dc=co,dc=th

ทุกอย่างเหมือนเดิม ยกเว้นบรรทัดสุดท้าย ที่เปลี่ยนเป็น Group manager

เมื่อเข้าหน้าเว็บก็จะพยกล่อง Basic Authen เหมือนเดิม แต่จะไม่ใส่สามารถใช้ punyapat.s เข้าได้ ต้องเป็น nareerat.s เท่านั้น เพราะว่ามีแค่ nareerat.s ที่อยู่ใน Group manager

basic authen

เกือบจบแล้วครับ เท่านี้เราก็สามารถกำหนดสิทธิ์ต่างๆ ผ่าน LDAP และทำให้ apache ทำงานตามได้ ซึ่งเราอาจจะไม่ใช้ .htaccess แล้วไป Config ใน Virtual Host เพื่อทำ proxy_pass ไป Service ที่เรามีให้บริการก็ได้

ต่อไปเราจะมาจำกัดสิทธิ์ของ User กันหน่อย เพราะเราไม่ต้องการให้ User ที่ไม่ใช่ Admin แก้ไขค่าใน LDAP ได้

  1. Enable Acccess Control ใน Server Configuration
Enable Access Control

เมื่อเรา Enable Access Control แล้ว User ทุกคนยกเว้น Admin จะไม่มีสิทธิ์ Browse Tree เลย (ถ้าทดลองสร้าง LDAP Connection ใหม่ด้วย User/Password punyapat.s ก็จะไม่เห็นอย่างอื่นเลยนอกจากตัว Entry ของมันเอง)

และ Basic Authen ที่เรา Setup ไว้ก็จะใช้ไม่ได้ เพราะว่า cn=binding ไม่มีสิทธิ์ Search หา Username ที่ได้รับมา (ซึ่งก็ทำให้มันไม่สามารถเช็คได้ว่า Username และ Password ถูกหรือไม่)

2. ต่อไปเราก็จะมากำหนดสิทธิ์ว่าให้ User แต่ละคนมีสิทธิ์มากแค่ไหนกัน แต่ก่อนจะเริ่มทำ เราต้องแสดง Attribute ของแต่ละ Entry ให้ครบก่อน โดยปกติแล้ว Apache Directory Studio จะไม่แสดง Attribute บางอย่าง หรือ Entry บางชนิด แต่เราต้องการเห็น Configuration เหล่านี้เพื่อทำงานต่อ โดยวิธีการทำให้ Apache Directory Studio แสดง Config ทุกอย่างคือ คลิกขวาที่ dc=insightera,dc=co,dc=th แล้วเลือก Fetch แล้วเลือกทุกข้อที่มีเลย เช่น Operational Attributes, Subentries

3. ต่อไปเราจะกำหนด Scope ว่าให้ Permission ที่กำลังจะ Set ทำงานกับ Entry ได้บ้าง โดยเราจะ Config ให้ทำงานกับ dc=insightera,dc=co,dc=th ด้วยการสร้าง Attribute ที่ชื่อ administrativeRole

สร้าง Attribute ชื่อ administrativeRole ใต้ dc=insightera,dc=co,dc=th

กำหนดค่า accessControlSpecificArea ให้ administrativeRole

กำหนดค่า accessControlSpecificArea ให้ administrativeRole
  • ระหว่างที่ทำงานอาจจะมี Popup แสดง Warning ขึ้นมา ไม่ต้องสนใจ กด OK แล้ว เดี๋ยวจะมีกล่องให้กรอกค่าขึ้นมา
  • ถ้าสร้าง Attribute ใหม่แล้วไม่เห็น Attribute ที่สร้างขึ้นมา ให้เลือกกลับไปดูข้อก่อนหน้าที่ให้กดแสดง Config ที่ปกติไม่ได้แสดง

4. สร้าง Entry subentry ที่จะเป็นตัวกำหนดสิทธิ์ใต้ dc=insightera,dc=co,dc=th โดยเลือก subentry และ accessControlSubentry

สร้าง subentry

ตั้ง cn=forBinding เพราะว่าเราจะอนุญาติให้ cn=binding สามารถ Browse และ Search หา User ที่ได้รับมาได้

ขั้นตอนต่อไปจะมี Popup ขึ้นมาถามรายละเอียดของการ Permission ถ้าไม่เห็นสิ่งนี้สามารถ Double Click ที่ prescriptiveACI ขึ้นมาดูก็ได้

เลือก Authentication Level เป็น Simple และเลือกให้สิทธิ์กับ User ด้วยการกำหนดชื่อ และใส่ DN ของ cn=binding เข้าไป กด Edit และ กด Add

เมื่อเลือก user เสร็จเรียบร้อยก็มาเพิ่ม Permission โดยการกด Add ข้างๆ กล่อง User Permissions และเลือก Entry กับ All User Attribute… และเลือก Permission Read Rights ทั้งหมด

เมื่อเสร็จเรียบร้อยก็จะได้ตามภาพ ตรง subtreeSpecification ถ้าไม่มี {} แบบนี้แสดงในภาพ ให้ Double Click เปิดกล่องแก้ไขขึ้นมาแล้วกด OK ปิดไป

เมื่อเสร็จเรียบร้อย เราก็จะได้ Entry ใหม่ และ cn=binding ก็จะสามารถใช้ค้นหา User ได้ตามปกติและ Basic Authen ก็จะกลับมาทำงานเหมือนเดิม โดย User คนอื่น จะไม่มีสิทธิ์ในการ Browse DIT ทำให้ไม่สามารถไปดึงเอาข้อมูลของ User คนอื่นมาดูได้

จบแล้วครับ บทความหน้าพบกับการทำ Basic Authen ด้วย Nginx ผ่าน LDAP และการ SSH เข้าเครื่อง Host ด้วย publickey จาก LDAP

Reference

--

--