ผลต่างระหว่างรุ่นของ "01204223/secrets"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 5 รุ่นระหว่างกลางโดยผู้ใช้คนเดียวกัน)
แถว 53: แถว 53:
  
 
=== จัดการกับรหัสผ่าน ===
 
=== จัดการกับรหัสผ่าน ===
 +
 +
ถ้าเรายังเก็บ config ของฐานข้อมูลไว้ใน main.py เมื่อเรา push ขึ้นไปที่ github รหัสผ่านทั้งหมดของเราก็อาจจะรั่วไหลไปจนทราบกันทั้งโลกได้  ดังนั้นเราจะต้องนำความลับดังกล่าวออกจากไฟล์ที่จะนำขึ้น version control system
 +
 +
เมื่อนำออกไปแล้ว มีสองวิธีคร่าว ๆ ที่จะทำให้โปรแกรมของเราทราบความลับดังกล่าวได้
 +
* อ่านจากไฟล์อื่น ๆ (ที่ต้องไม่ถูกนำเข้า version control ซึ่งโดยมากจะต้องระบุให้ชัดเจนใน .gitignore '''สำคัญมาก''')
 +
* อ่านจาก environment variable (ยกตัวอย่างเช่น FLASK_APP ที่เราต้องตั้งก่อนเรียก flask run --debug ทุกครั้ง)
 +
 +
การอ่าน config จากไฟล์จะสะดวกในการใช้ระหว่าง development แต่การอ่านค่าจาก environment จะสะดวกกับการ deploy มากกว่า
 +
 +
อย่างไรก็ตาม เราสามารถเลือกใช้ไลบรารี [https://pypi.org/project/python-dotenv/ python-dotenv] เพื่อทำให้เราได้ความสะดวกจากทั้งสองแนวทาง โดยเราจะใส่ config ต่าง ๆ ในไฟล์ ชื่อ <tt>.env</tt> และใช้ไลบรารีโหลดค่าดังกล่าวมาไว้ใน environment variable ซึ่งจะถูกโหลดเข้า Flask อีกที (โดยอัตโนมัติ)
 +
 +
ขั้นแรก เราจะต้องติดตั้ง python-dotenv
 +
 +
pip install python-dotenv
 +
 +
อย่าลืม pip freeze ไปใส่ requirements.txt ด้วย
 +
 +
จากนั้นเราจะสร้างไฟล์ชื่อ .env (ในไดเร็กทอรี backend) โดยนำ config สองค่าไปใส่ดังนี้  (แทนค่าใน USERNAME, PASSWORD, DATABASENAME ให้เรียบร้อย
 +
 +
SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME
 +
JWT_SECRET_KEY=fdsjkfjioi2rjshr2345hrsh043j5oij5545
 +
 +
แล้วแก้โค้ดใน main.py ให้อ่านค่าจาก config ทั้งสองจาก environment variable แทน
 +
 +
ก่อนอื่นเพิ่ม import os ที่ตอนต้นโค้ด
 +
 +
<syntaxhighlight lang="python">
 +
import os
 +
</syntaxhighlight>
 +
 +
แล้วแก้บรรทัด config ให้เป็น (''หมายเหตุ:'' เราใส่ค่า default ไปด้วย เพื่อให้ github action สามารถทำงานได้ -- ไม่เช่นนั้นตอนทำงานจะมี error)
 +
 +
<syntaxhighlight lang="python">
 +
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('SQLALCHEMY_DATABASE_URI','sqlite:///todos.db')
 +
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY','fdslkfjsdlkufewhjroiewurewrew')
 +
</syntaxhighlight>
 +
 +
จากนั้นถ้าเรียก flask run --debug ทุกอย่างน่าจะใช้งานได้ไม่ต่างจากเดิม
 +
 +
'''ก่อนจะทำต่อไป สิ่งที่เราควรจะทำทันทีคือ เพิ่ม .env ลงใน .gitignore''' เพื่อป้องกันไม่ให้เรา add .env เข้าไปใน git repository
 +
 +
ให้เพิ่มบรรทัดด้านล่างลงใน .gitignore ที่อยู่ใน backend
 +
 +
.env
 +
 +
จากนั้นลองสั่ง git status  ควรจะไม่เห็นไฟล์ .env ในรายการ
 +
 +
==== ทดสอบส่งค่าให้ทาง environment ====
 +
 +
เราจะทดสอบว่า Flask อ่าน config จาก environment หรือไม่
 +
 +
ในขั้นแรกให้ลองแก้ไฟล์ .env และใส่ comment บรรทัด SQLALCHEMY_DATABASE_URI
 +
 +
# SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME
 +
 +
แล้วลองเรียก
 +
 +
flask db check
 +
 +
จะได้รับ error เป็นผลลัพธ์
 +
 +
จากนั้นให้ลองสั่ง (ใน mac/ubuntu)
 +
 +
export SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME
 +
 +
หรือ (ใน windows)
 +
 +
set SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME
 +
 +
จากนั้นลองเรียก
 +
 +
flask db check
 +
 +
แล้วทดลองใช้อีกครั้ง น่าจะกลับมาทำงานได้แบบเดิม
 +
 +
ก่อนจะทำงานต่อให้ไปแก้ .env กลับให้เป็นแบบเดิม (เอา comment ออก)  แล้วทดลองว่าแอพทำงานได้ตามปกติ
 +
 +
{{กล่องฟ้า|
 +
'''🄶''' เมื่อทดลองใช้เรียบร้อย ให้เก็บการแก้ไข และ commit (ดูอีกทีว่าไฟล์ .env ไม่ถูกเพิ่มเข้าไป) จากนั้น push งานไปที่ github เพื่อดูผลการเทสทั้งหมดอีกครั้ง
 +
}}

รุ่นแก้ไขปัจจุบันเมื่อ 08:20, 27 กุมภาพันธ์ 2569

หน้านี้เป็นส่วนของวิชา 01204223

เราจะฝึกจัดการกับข้อมูลที่เป็นความลับในการพัฒนาเว็บแอพ

ก่อนอื่นอ่านภาพรวมในการจัดการก่อน อ่านที่นี่: แนวทางทั่วไปในการจัดการกับความลับ

เราได้ส่งบัญชีและรหัสผ่านผู้ใช้ mysql บนเครื่อง p1.secondtrain.org แล้ว เราจะเริ่มโดยย้ายฐานข้อมูลของ Todo app ของเราไปใช้ mysql บนเซิร์ฟเวอร์ จากนั้นเราจะจัดการกับความลับนี้

เปลี่ยนฐานข้อมูล

เราจะย้ายไปใช้ฐานข้อมูล mysql บนเซิร์ฟเวอร์ p1.secondtrain.org ให้ไปตรวจสอบบัญชีที่แจกให้ใน google sheet

ถ้ามีโปรแกรม client mysql ในเครื่อง ให้ทดลอง access database ที่กำหนดให้ดูก่อน ถ้าสามารถตรวจสอบได้ จะทำให้ debug โค้ดที่เราจะทดลองต่อไปได้ง่ายขึ้น (อาจจะง่ายขึ้นกว่าใช้ sqlite)

เราจะปรับให้ Flask ใช้ฐานข้อมูลที่กำหนดให้ ก่อนอื่นต้องติดตั้งไลบรารีสำหรับเชื่อมต่อ mysql บน python เสียก่อน

เริ่มโดยการ activate virtual environment ก่อนจะสั่ง

pip install mysqlclient

เมื่อสั่งเรียบร้อย ให้อัพเดท requirements.txt โดยสั่ง

pip freeze > requirements.txt

เราจะเปลี่ยน SQLALCHEMY_DATABASE_URI ให้เป็นฐานข้อมูลใหม่ โดยแก้บรรทัดใน main.py ให้เป็น

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME'

โดยแทนค่า USERNAME, PASSWORD, และ DATABASENAME ให้เป็นไปตามที่กำหนดให้

จากนั้น ให้ migrate ฐานข้อมูล โดยสั่ง

flask db upgrade

ถ้ากำหนดค่าเรียบร้อยน่าจะเห็นผลลัพธ์ดังนี้

INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 45b68ed6f7cf, Initial migration
INFO  [alembic.runtime.migration] Running upgrade 45b68ed6f7cf -> dbe42139c979, add comment
INFO  [alembic.runtime.migration] Running upgrade dbe42139c979 -> 2da8e1a15425, Add User

ถ้าสามารถดูฐานข้อมูลประกอบไปด้วย อาจจะทำให้เห็นภาพการทำงานชัดเจนขึ้น

ให้สั่งสร้างผู้ใช้

flask create-user admin "Admin Fullname" helloworld

จากนั้นให้ทดลองใช้ todo app ว่าทำงานได้ปกติ เพิ่ม todo item ได้ เพิ่ม comment ได้

จัดการกับรหัสผ่าน

ถ้าเรายังเก็บ config ของฐานข้อมูลไว้ใน main.py เมื่อเรา push ขึ้นไปที่ github รหัสผ่านทั้งหมดของเราก็อาจจะรั่วไหลไปจนทราบกันทั้งโลกได้ ดังนั้นเราจะต้องนำความลับดังกล่าวออกจากไฟล์ที่จะนำขึ้น version control system

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

  • อ่านจากไฟล์อื่น ๆ (ที่ต้องไม่ถูกนำเข้า version control ซึ่งโดยมากจะต้องระบุให้ชัดเจนใน .gitignore สำคัญมาก)
  • อ่านจาก environment variable (ยกตัวอย่างเช่น FLASK_APP ที่เราต้องตั้งก่อนเรียก flask run --debug ทุกครั้ง)

การอ่าน config จากไฟล์จะสะดวกในการใช้ระหว่าง development แต่การอ่านค่าจาก environment จะสะดวกกับการ deploy มากกว่า

อย่างไรก็ตาม เราสามารถเลือกใช้ไลบรารี python-dotenv เพื่อทำให้เราได้ความสะดวกจากทั้งสองแนวทาง โดยเราจะใส่ config ต่าง ๆ ในไฟล์ ชื่อ .env และใช้ไลบรารีโหลดค่าดังกล่าวมาไว้ใน environment variable ซึ่งจะถูกโหลดเข้า Flask อีกที (โดยอัตโนมัติ)

ขั้นแรก เราจะต้องติดตั้ง python-dotenv

pip install python-dotenv

อย่าลืม pip freeze ไปใส่ requirements.txt ด้วย

จากนั้นเราจะสร้างไฟล์ชื่อ .env (ในไดเร็กทอรี backend) โดยนำ config สองค่าไปใส่ดังนี้ (แทนค่าใน USERNAME, PASSWORD, DATABASENAME ให้เรียบร้อย

SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME
JWT_SECRET_KEY=fdsjkfjioi2rjshr2345hrsh043j5oij5545

แล้วแก้โค้ดใน main.py ให้อ่านค่าจาก config ทั้งสองจาก environment variable แทน

ก่อนอื่นเพิ่ม import os ที่ตอนต้นโค้ด

import os

แล้วแก้บรรทัด config ให้เป็น (หมายเหตุ: เราใส่ค่า default ไปด้วย เพื่อให้ github action สามารถทำงานได้ -- ไม่เช่นนั้นตอนทำงานจะมี error)

app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('SQLALCHEMY_DATABASE_URI','sqlite:///todos.db') 
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY','fdslkfjsdlkufewhjroiewurewrew')

จากนั้นถ้าเรียก flask run --debug ทุกอย่างน่าจะใช้งานได้ไม่ต่างจากเดิม

ก่อนจะทำต่อไป สิ่งที่เราควรจะทำทันทีคือ เพิ่ม .env ลงใน .gitignore เพื่อป้องกันไม่ให้เรา add .env เข้าไปใน git repository

ให้เพิ่มบรรทัดด้านล่างลงใน .gitignore ที่อยู่ใน backend

.env

จากนั้นลองสั่ง git status ควรจะไม่เห็นไฟล์ .env ในรายการ

ทดสอบส่งค่าให้ทาง environment

เราจะทดสอบว่า Flask อ่าน config จาก environment หรือไม่

ในขั้นแรกให้ลองแก้ไฟล์ .env และใส่ comment บรรทัด SQLALCHEMY_DATABASE_URI

# SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME

แล้วลองเรียก

flask db check

จะได้รับ error เป็นผลลัพธ์

จากนั้นให้ลองสั่ง (ใน mac/ubuntu)

export SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME

หรือ (ใน windows)

set SQLALCHEMY_DATABASE_URI=mysql://USERNAME:PASSWORD@p1.secondtrain.org/DATABASENAME

จากนั้นลองเรียก

flask db check

แล้วทดลองใช้อีกครั้ง น่าจะกลับมาทำงานได้แบบเดิม

ก่อนจะทำงานต่อให้ไปแก้ .env กลับให้เป็นแบบเดิม (เอา comment ออก) แล้วทดลองว่าแอพทำงานได้ตามปกติ

🄶 เมื่อทดลองใช้เรียบร้อย ให้เก็บการแก้ไข และ commit (ดูอีกทีว่าไฟล์ .env ไม่ถูกเพิ่มเข้าไป) จากนั้น push งานไปที่ github เพื่อดูผลการเทสทั้งหมดอีกครั้ง