ມີ 2 ແບບ
| ແບບ | ຂໍ Token ຈາກ | ເໝາະກັບ |
|---|---|---|
| ຝັງກັບບໍລິການ | ເຄື່ອງທີ່ບໍລິການແລ່ນຢູ່ ບໍ່ມີ Secret ແລະ ເອີ້ນຈາກພາຍນອກບໍ່ໄດ້ | ໂຄ້ດໃນ Container ຫຼື Function |
| Client ID ແລະ Secret | ບ່ອນໃດກໍໄດ້ດ້ວຍ Secret ບໍລິການກໍເລືອກໃຊ້ໄດ້ເຊັ່ນກັນ | ເຊີບເວີຂອງທ່ານ CI ຫຼື Cloud ອື່ນ |
ທຸກ Project ມີ Service Account ແບບຝັງເປັນ ຄ່າເລີ່ມຕົ້ນ 1 ອັນ ທຸກບໍລິການໃຊ້ອັນນີ້ຈົນກວ່າຈະເລືອກອັນອື່ນຕອນສ້າງ ຫຼື ໃນໜ້າຕັ້ງຄ່າ ແລະ ເຮັດຫຍັງບໍ່ໄດ້ຈົນກວ່າຈະໃຫ້ສິດ
ໃຫ້ສິດ
- ເປີດ Service Account ໃນ Console ແລ້ວເລືອກ ຫຼື ສ້າງໃໝ່
- ທີ່ຫົວຂໍ້ ສິດ ເລືອກບໍລິການ ເລືອກຕົວທີ່ຕ້ອງການ (ຫຼື ທຸກຕົວໃນ Project) ແລະ ລະດັບສິດ
- ໃຊ້ໄດ້ພາຍໃນບໍ່ເທົ່າໃດວິນາທີ ບໍລິການທີ່ໃຊ້ Service Account ນີ້ຈະເຂົ້າເຖິງ Database, Cache ຫຼື Container ນັ້ນຜ່ານເຄືອຂ່າຍຂອງ Project ໄດ້ນຳ ເອົາສິດອອກກໍມີຜົນພາຍໃນບໍ່ເທົ່າໃດວິນາທີເຊັ່ນກັນ ເຖິງແມ່ນ Token ທີ່ອອກໄປແລ້ວ
| ບໍລິການ | ສິດ | ໂຄ້ດໃຊ້ງານແນວໃດ |
|---|---|---|
| Database | ອ່ານຢ່າງດຽວ ອ່ານ ແລະ ຂຽນ | ກົດ Connect ບໍ່ຕ້ອງມີລະຫັດຜ່ານ ຫຼື ໃຊ້ Login ຊົ່ວຄາວຈາກພາຍນອກ |
| Cache | ອ່ານຢ່າງດຽວ ອ່ານ ແລະ ຂຽນ | ກົດ Connect ບໍ່ຕ້ອງມີລະຫັດຜ່ານ ຫຼື ໃຊ້ Login ຊົ່ວຄາວຈາກພາຍນອກ |
| Object Storage | ອ່ານ ຂຽນ ລຶບ | ສົ່ງ Token ໄປທີ່ REST API ເຄື່ອງມືແບບ S3 ຍັງຕ້ອງໃຊ້ Access Key |
| Queue | ສົ່ງ ຮັບ ຫຼື ທັງສອງຢ່າງ ແລະ ລ້າງຄິວ | ສົ່ງ Token ໄປທີ່ REST API |
| Container ແລະ Function | ເອີ້ນໃຊ້ | ສົ່ງ Token ທີ່ອອກໃຫ້ບໍລິການນັ້ນໄປທີ່ທີ່ຢູ່ສາທາລະນະຂອງມັນ |
Database ແລະ Cache: ກົດ Connect
ໃນໜ້າ Container ຫຼື Function ເປີດແທັບ ເຊື່ອມຕໍ່ ເລືອກປາຍທາງ ແລະ ສິດ ແລ້ວກົດ Connect ລະບົບເພີ່ມຕົວແປ DATABASE_URL ຫຼື REDIS_URL ທີ່ບໍ່ມີລະຫັດຜ່ານ ໂຄ້ດໃຊ້ URL ນີ້ກັບ driver ໄດ້ຕາມປົກກະຕິ ເຄື່ອງທີ່ແລ່ນຢູ່ຈະ Login ໃຫ້ ບໍ່ມີລະຫັດຜ່ານຢູ່ໃນຕົວແປ ໃນໂຄ້ດ ຫຼື ໃນໜ້າ Console ແລະ URL ໃຊ້ໄດ້ສະເພາະຈາກໃນ Service ນັ້ນ
Dev ທີ່ Deploy ໄດ້ຍັງອ່ານຂໍ້ມູນຜ່ານ connection ນີ້ໄດ້ ຖ້າບໍ່ຕ້ອງການໃຫ້ເຫັນຂໍ້ມູນຈິງ ໃຫ້ແຍກ Production ເປັນອີກ Project ລະຫັດຜ່ານຫຼັກຂອງຖານຂໍ້ມູນເບິ່ງໄດ້ສະເພາະ Owner ແລະ Admin
ໂປຣແກຣມນອກລະບົບໃຊ້ Service Account ແບບມີ Client ID ແລະ Secret ແລກ Token ເປັນ Login ຊົ່ວຄາວຕາມຕົວຢ່າງດ້ານລຸ່ມ ໂຄ້ດໃນ Container ຫຼື Function ແລກບໍ່ໄດ້
SDK
| ພາສາ | ຕ້ອງການ | ຕິດຕັ້ງ |
|---|---|---|
| Node.js | 18.17+ | npm install @thailandhosting/identity |
| Python | 3.9+ | pip install thailandhosting-identity |
| Go | 1.23+ | go get github.com/mrzack99s/thailandhosting-identity-sdk-go |
import { defaultCredential } from '@thailandhosting/identity';
import { Client as Queues } from '@thailandhosting/queue-service';
// In a Container or Function this needs nothing. Elsewhere set
// TH_CLIENT_ID and TH_CLIENT_SECRET.
const cred = defaultCredential();
const queues = new Queues({ region: 'th-bkk-1', tokenProvider: () => cred.getToken() });
// From outside the platform. In a Container or Function, click Connect instead.
const login = await cred.databaseCredentials('orders');
const pool = new pg.Pool({ connectionString: login.private.url });from thailandhosting_identity import default_credential
from thailandhosting_queueservice import Client as Queues
# In a Container or Function this needs nothing. Elsewhere set
# TH_CLIENT_ID and TH_CLIENT_SECRET.
cred = default_credential()
queues = Queues(region="th-bkk-1", token_provider=cred.get_token)
# From outside the platform. In a Container or Function, click Connect instead.
login = cred.database_credentials("orders")
conn = psycopg.connect(login["private"]["url"])import identity "github.com/mrzack99s/thailandhosting-identity-sdk-go"
// In a Container or Function this needs nothing. Elsewhere set
// TH_CLIENT_ID and TH_CLIENT_SECRET.
cred, err := identity.Default()
queues, err := queueservice.New(queueservice.Config{Region: "th-bkk-1", TokenSource: cred.TokenSource("")})
// From outside the platform. In a Container or Function, click Connect instead.
login, err := cred.DatabaseCredentials(ctx, "orders")
db, err := sql.Open("pgx", login.Private.URL)ພາສາອື່ນ: ເອີ້ນ HTTP ໂດຍກົງ
ຈາກໃນ Container ຫຼື Function ໃຫ້ຖາມເຄື່ອງທີ່ແລ່ນຢູ່ ຄຳຂໍຕ້ອງມີ Metadata: true ເກັບຄຳຕອບໄວ້ໃຊ້ຈົນໃກ້ຮອດ expires_on
# Inside a Container or Function. The address answers only there.
curl -H 'Metadata: true' http://169.254.169.254/identity/oauth2/token
# For calling another Container, name it as the audience:
curl -H 'Metadata: true' 'http://169.254.169.254/identity/oauth2/token?audience=https://orders.containers.th-bkk-1.thailandhosting.com'
# {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,"expires_on":1793355792,"client_id":"sa-..."}ຖ້າໃຊ້ Client ID ແລະ Secret ໃຫ້ຂໍຈາກ Token Endpoint:
# From anywhere, with a client ID and secret (OAuth 2.0 client credentials).
curl https://api.thailandhosting.com/v1/identity/token \
-d grant_type=client_credentials \
-d client_id=$TH_CLIENT_ID \
-d client_secret=$TH_CLIENT_SECRETແລ້ວນຳ Token ໄປໃຊ້:
# Queue Service and Object Storage: send the token as a bearer.
curl -H "Authorization: Bearer $TOKEN" https://queues.thailandhosting.com/th-bkk-1/v1/queues/jobs/messages -d '{"body":"hello"}'
# Database or Cache, from outside the platform: exchange the token for a login.
# In a Container or Function, click Connect and use the URL it adds instead.
curl -H "Authorization: Bearer $TOKEN" https://api.thailandhosting.com/v1/identity/database-credentials -d '{"database":"orders"}'
# {"username":"sa_...","password":"...","database":"orders","expiresAt":"...","private":{"host":"orders.internal","port":5432,"url":"postgresql://..."}}
# Another Container or Function: a token made for its address.
curl -H "Authorization: Bearer $TOKEN" https://orders.containers.th-bkk-1.thailandhosting.com/itemsຄຳຂໍດຽວກັນໃນພາສາອື່ນ:
<?php // PHP, inside a Container or Function
$ctx = stream_context_create(['http' => ['header' => "Metadata: true\r\n"]]);
$token = json_decode(file_get_contents('http://169.254.169.254/identity/oauth2/token', false, $ctx))->access_token;// Java 11+, inside a Container or Function
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("http://169.254.169.254/identity/oauth2/token"))
.header("Metadata", "true").build();
var body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
// Read access_token and expires_on with your JSON library.// C#, inside a Container or Function
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("Metadata", "true");
var body = await http.GetStringAsync("http://169.254.169.254/identity/oauth2/token");
var token = JsonDocument.Parse(body).RootElement.GetProperty("access_token").GetString();# Ruby, inside a Container or Function
require 'net/http'; require 'json'
uri = URI('http://169.254.169.254/identity/oauth2/token')
token = JSON.parse(Net::HTTP.get(uri, 'Metadata' => 'true'))['access_token']ກວດ Token ທີ່ຄົນອື່ນສົ່ງມາ
SDK ມີ Verifier ໃຫ້ Token ອອກໃຫ້ຜູ້ຮັບ (audience) ຄົນດຽວ ຈຶ່ງຕ້ອງກວດວ່າເປັນຂອງທ່ານ Token ທີ່ສົ່ງໃຫ້ບໍລິການອື່ນຈະໄດ້ນຳມາໃຊ້ກັບບໍລິການຂອງທ່ານບໍ່ໄດ້ ລະບົບກວດ Token ໃຫ້ສະເພາະທີ່ທີ່ຢູ່ສາທາລະນະຂອງ Container ຖ້າເອີ້ນໂດຍກົງຜ່ານເຄືອຂ່າຍຂອງ Project ໃຫ້ກວດໃນໂຄ້ດຂອງທ່ານ
# Published keys (JWKS) and discovery, for any JWT library:
https://api.thailandhosting.com/v1/identity/keys
https://api.thailandhosting.com/v1/identity/.well-known/openid-configuration
# Check: alg ES256, iss https://api.thailandhosting.com/v1/identity, aud your own name, exp, nbf.Token ໃຊ້ໄດ້ 1 ຊົ່ວໂມງ ໃຜໄດ້ໄປກໍໃຊ້ໄດ້ຈົນໝົດອາຍຸເຖິງແມ່ນຈາກພາຍນອກ ຢ່າຂຽນລົງ Log ແລະ ຢ່າສົ່ງໃຫ້ບໍລິການທີ່ບໍ່ໄວ້ໃຈ
ຖ້າພົບບັນຫາ
ໄດ້ 403 ຫຼື no_identity ຈາກທີ່ຢູ່ຂອງ Identity
ສະເພາະ Container ແລະ Function ທີ່ຂໍ Token ທີ່ນີ້ໄດ້ ເວັບໄຊ Database Cache ແລະ Mail ບໍ່ໄດ້ແລ່ນໂຄ້ດຂອງທ່ານຈຶ່ງຂໍບໍ່ໄດ້
ເຊື່ອມຕໍ່ 169.254.169.254 ບໍ່ໄດ້
ໂຄ້ດບໍ່ໄດ້ແລ່ນໃນ Container ຫຼື Function ຖ້າແລ່ນເທິງເຄື່ອງຂອງທ່ານ ໃຫ້ໃຊ້ແບບ Client ID ແລະ Secret ແລ້ວຕັ້ງ TH_CLIENT_ID ແລະ TH_CLIENT_SECRET
Login ຂອງຖານຂໍ້ມູນໃຊ້ບໍ່ໄດ້ແລ້ວ
Login ມີອາຍຸເປັນຊົ່ວໂມງ ໃຫ້ຂໍໃໝ່ ສ່ວນ Connection ທີ່ເປີດຢູ່ຍັງໃຊ້ຕໍ່ໄດ້