Sovereign Cloud - Self-Hosted Lisans Sistemi
Magnesify Sovereign Cloud (MSC), Rust programlama dili ile geliştirilmiş, kendi sunucunuzda çalıştırabileceğiniz güvenli bir lisans yönetim sistemidir. Bu sistem, yazılım lisanslarınızı merkezi olarak yönetmenizi, doğrulamanızı ve kontrol etmenizi sağlar.
🚀 Özellikler
- Self-Hosted: Kendi sunucunuzda tam kontrol
- Güvenli API: Admin kimlik doğrulama ile korumalı endpointler
- IP Bazlı Lisanslama: IP adresine bağlı lisans kontrolü
- Sürekli Güvenlik Kontrolü: Arka planda çalışan lisans doğrulama sistemi
- CLI Arayüzü: Komut satırından kolay yönetim
- SQLite Veritabanı: Hafif ve taşınabilir veri saklama
- RESTful API: Modern web servisleri ile entegrasyon
🔧 Kurulum
Gereksinimler
- Rust 1.70+
- SQLite3
- Linux/Unix sistem (makine ID desteği için)
⚙️ Konfigürasyon
Sistem ilk çalıştırıldığında msc.yaml
dosyası otomatik olarak oluşturulur:
app:
protocol: "http"
token: "LUTFEN_BURAYA_LISANS_TOKENINIZI_GIRIN"
server:
host: "127.0.0.1"
default_port: 4050
database:
path: "licenses.db"
Önemli: app.token
alanını geçerli bir lisans tokeni ile güncelleyin.
🚀 Kullanım
Sunucuyu Başlatma
# Varsayılan port (4050) ile başlatma
./msc start
# Özel port ile başlatma
./msc start --port 8080
Veritabanı Yönetimi
# Veritabanı şemasını oluştur/güncelle
./msc db migrate
Kullanıcı Yönetimi
# Admin kullanıcısı oluştur
./msc create user --email admin@example.com --role ADMIN
# Normal kullanıcı oluştur
./msc create user --email user@example.com --role USER
# Kullanıcı sil
./msc delete user --email user@example.com
API Anahtarı Oluşturma
# Admin kullanıcısı için API anahtarı oluştur
./msc generate-key --email admin@example.com
Lisans Yönetimi
# Lisans oluştur
./msc create license --product "my-app" --user "user123" --ip "192.168.1.100"
# Özel MID ile lisans oluştur
./msc create license --mid "abc123" --product "my-app" --user "user123" --ip "192.168.1.100"
# Lisans sil
./msc delete license --mid "abc123"
# Tüm lisansları listele
./msc list
🌐 API Endpointleri
Tüm API endpointleri /api/licenses
prefix'i altında bulunur ve admin kimlik doğrulama gerektirir.
Kimlik Doğrulama
API isteklerinde X-API-Key
header'ında geçerli bir API anahtarı gönderilmelidir:
curl -H "X-API-Key: your-api-key-here" http://localhost:4050/api/licenses/list
Endpointler
1. Lisansları Listele
GET /api/licenses/list
Yanıt:
{
"message_type": "success",
"message": "Licenses listed successfully.",
"endpoint": "/api/licenses/list",
"data": [
{
"id": 1,
"mid": "abc-mag-def-ghi",
"product_id": "my-app",
"user_id": "user123",
"ip_address": "192.168.1.100",
"is_active": true,
"created_at": "2024-01-01T00:00:00Z"
}
],
"timestamp": "2024-01-01T00:00:00Z"
}
Örnek Kodlar:
Java (OkHttp):
import okhttp3.*;
import java.io.IOException;
public class MSCClient {
private static final String BASE_URL = "http://localhost:4050";
private static final String API_KEY = "your-api-key-here";
public static void listLicenses() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/list")
.addHeader("X-API-Key", API_KEY)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
JavaScript (Fetch):
const BASE_URL = 'http://localhost:4050';
const API_KEY = 'your-api-key-here';
async function listLicenses() {
try {
const response = await fetch(`${BASE_URL}/api/licenses/list`, {
method: 'GET',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('Licenses:', data);
} catch (error) {
console.error('Error:', error);
}
}
// Kullanım
listLicenses();
PHP (cURL):
<?php
$baseUrl = 'http://localhost:4050';
$apiKey = 'your-api-key-here';
function listLicenses() {
global $baseUrl, $apiKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/list');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
echo "Licenses: " . print_r($data, true);
} else {
echo "Error: HTTP $httpCode";
}
}
listLicenses();
?>
2. Lisans Oluştur
POST /api/licenses/create
Content-Type: application/json
{
"product_id": "my-app",
"user_id": "user123",
"ip_address": "192.168.1.100"
}
Örnek Kodlar:
Java (OkHttp):
public static void createLicense() throws IOException {
OkHttpClient client = new OkHttpClient();
String jsonBody = "{\"product_id\":\"my-app\",\"user_id\":\"user123\",\"ip_address\":\"192.168.1.100\"}";
RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json"));
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/create")
.addHeader("X-API-Key", API_KEY)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
JavaScript (Fetch):
async function createLicense() {
const licenseData = {
product_id: 'my-app',
user_id: 'user123',
ip_address: '192.168.1.100'
};
try {
const response = await fetch(`${BASE_URL}/api/licenses/create`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(licenseData)
});
const data = await response.json();
console.log('License created:', data);
} catch (error) {
console.error('Error:', error);
}
}
PHP (cURL):
function createLicense() {
global $baseUrl, $apiKey;
$licenseData = [
'product_id' => 'my-app',
'user_id' => 'user123',
'ip_address' => '192.168.1.100'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/create');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($licenseData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "License created: " . print_r($data, true);
}
3. Lisans Sil
DELETE /api/licenses/delete
Content-Type: application/json
{
"mid": "abc-mag-def-ghi"
}
Örnek Kodlar:
Java (OkHttp):
public static void deleteLicense(String mid) throws IOException {
OkHttpClient client = new OkHttpClient();
String jsonBody = "{\"mid\":\"" + mid + "\"}";
RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json"));
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/delete")
.addHeader("X-API-Key", API_KEY)
.delete(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
JavaScript (Fetch):
async function deleteLicense(mid) {
const deleteData = { mid: mid };
try {
const response = await fetch(`${BASE_URL}/api/licenses/delete`, {
method: 'DELETE',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(deleteData)
});
const data = await response.json();
console.log('License deleted:', data);
} catch (error) {
console.error('Error:', error);
}
}
PHP (cURL):
function deleteLicense($mid) {
global $baseUrl, $apiKey;
$deleteData = ['mid' => $mid];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/delete');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($deleteData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "License deleted: " . print_r($data, true);
}
4. Lisans Doğrula
POST /api/licenses/validate
Content-Type: application/json
{
"product_id": "my-app",
"user_id": "user123"
}
Yanıt:
{
"message_type": "success",
"message": "License is valid.",
"endpoint": "/api/licenses/validate",
"data": {
"valid": true
},
"timestamp": "2024-01-01T00:00:00Z"
}
Örnek Kodlar:
Java (OkHttp):
public static void validateLicense() throws IOException {
OkHttpClient client = new OkHttpClient();
String jsonBody = "{\"product_id\":\"my-app\",\"user_id\":\"user123\"}";
RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json"));
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/validate")
.addHeader("X-API-Key", API_KEY)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String responseBody = response.body().string();
System.out.println("Validation response: " + responseBody);
// JSON parse etmek için Jackson veya Gson kullanabilirsiniz
if (response.isSuccessful()) {
System.out.println("License is valid!");
} else {
System.out.println("License validation failed!");
}
}
}
JavaScript (Fetch):
async function validateLicense() {
const validateData = {
product_id: 'my-app',
user_id: 'user123'
};
try {
const response = await fetch(`${BASE_URL}/api/licenses/validate`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(validateData)
});
const data = await response.json();
if (data.data && data.data.valid) {
console.log('✅ License is valid!');
} else {
console.log('❌ License is invalid!');
}
console.log('Validation result:', data);
} catch (error) {
console.error('Error:', error);
}
}
PHP (cURL):
function validateLicense() {
global $baseUrl, $apiKey;
$validateData = [
'product_id' => 'my-app',
'user_id' => 'user123'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/validate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($validateData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode === 200 && isset($data['data']['valid']) && $data['data']['valid']) {
echo "✅ License is valid!\n";
} else {
echo "❌ License is invalid!\n";
}
echo "Validation result: " . print_r($data, true);
}
5. MID ile Lisans Getir
GET /api/licenses/get-by-mid/{mid}
Örnek Kodlar:
Java (OkHttp):
public static void getLicenseByMid(String mid) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/get-by-mid/" + mid)
.addHeader("X-API-Key", API_KEY)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("License: " + response.body().string());
}
}
JavaScript (Fetch):
async function getLicenseByMid(mid) {
try {
const response = await fetch(`${BASE_URL}/api/licenses/get-by-mid/${mid}`, {
method: 'GET',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('License:', data);
} catch (error) {
console.error('Error:', error);
}
}
PHP (cURL):
function getLicenseByMid($mid) {
global $baseUrl, $apiKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/get-by-mid/' . urlencode($mid));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "License: " . print_r($data, true);
}
6. MID Prefix ile Lisansları Listele
GET /api/licenses/list-by-mid/{mid_prefix}
Örnek Kodlar:
Java (OkHttp):
public static void listLicensesByMidPrefix(String midPrefix) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/list-by-mid/" + midPrefix)
.addHeader("X-API-Key", API_KEY)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Licenses with prefix: " + response.body().string());
}
}
JavaScript (Fetch):
async function listLicensesByMidPrefix(midPrefix) {
try {
const response = await fetch(`${BASE_URL}/api/licenses/list-by-mid/${midPrefix}`, {
method: 'GET',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('Licenses with prefix:', data);
} catch (error) {
console.error('Error:', error);
}
}
PHP (cURL):
function listLicensesByMidPrefix($midPrefix) {
global $baseUrl, $apiKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/api/licenses/list-by-mid/' . urlencode($midPrefix));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Licenses with prefix: " . print_r($data, true);
}
Tam Örnek: MSC Client Sınıfları
Java Client Sınıfı:
import okhttp3.*;
import java.io.IOException;
public class MSCClient {
private static final String BASE_URL = "http://localhost:4050";
private final String apiKey;
private final OkHttpClient client;
public MSCClient(String apiKey) {
this.apiKey = apiKey;
this.client = new OkHttpClient();
}
public String listLicenses() throws IOException {
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/list")
.addHeader("X-API-Key", apiKey)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
public String createLicense(String productId, String userId, String ipAddress) throws IOException {
String jsonBody = String.format(
"{\"product_id\":\"%s\",\"user_id\":\"%s\",\"ip_address\":\"%s\"}",
productId, userId, ipAddress
);
RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json"));
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/create")
.addHeader("X-API-Key", apiKey)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
public String validateLicense(String productId, String userId) throws IOException {
String jsonBody = String.format(
"{\"product_id\":\"%s\",\"user_id\":\"%s\"}",
productId, userId
);
RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json"));
Request request = new Request.Builder()
.url(BASE_URL + "/api/licenses/validate")
.addHeader("X-API-Key", apiKey)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
}
// Kullanım
MSCClient client = new MSCClient("your-api-key-here");
String licenses = client.listLicenses();
System.out.println(licenses);
JavaScript Client Sınıfı:
class MSCClient {
constructor(apiKey, baseUrl = 'http://localhost:4050') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const config = {
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json',
...options.headers
},
...options
};
const response = await fetch(url, config);
return await response.json();
}
async listLicenses() {
return await this.request('/api/licenses/list', { method: 'GET' });
}
async createLicense(productId, userId, ipAddress) {
const data = { product_id: productId, user_id: userId, ip_address: ipAddress };
return await this.request('/api/licenses/create', {
method: 'POST',
body: JSON.stringify(data)
});
}
async validateLicense(productId, userId) {
const data = { product_id: productId, user_id: userId };
return await this.request('/api/licenses/validate', {
method: 'POST',
body: JSON.stringify(data)
});
}
async deleteLicense(mid) {
const data = { mid: mid };
return await this.request('/api/licenses/delete', {
method: 'DELETE',
body: JSON.stringify(data)
});
}
}
// Kullanım
const client = new MSCClient('your-api-key-here');
client.listLicenses().then(licenses => console.log(licenses));
PHP Client Sınıfı:
<?php
class MSCClient {
private $apiKey;
private $baseUrl;
public function __construct($apiKey, $baseUrl = 'http://localhost:4050') {
$this->apiKey = $apiKey;
$this->baseUrl = $baseUrl;
}
private function request($endpoint, $method = 'GET', $data = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->baseUrl . $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $this->apiKey,
'Content-Type: application/json'
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
} elseif ($method === 'DELETE') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
'status' => $httpCode,
'data' => json_decode($response, true)
];
}
public function listLicenses() {
return $this->request('/api/licenses/list');
}
public function createLicense($productId, $userId, $ipAddress) {
$data = [
'product_id' => $productId,
'user_id' => $userId,
'ip_address' => $ipAddress
];
return $this->request('/api/licenses/create', 'POST', $data);
}
public function validateLicense($productId, $userId) {
$data = [
'product_id' => $productId,
'user_id' => $userId
];
return $this->request('/api/licenses/validate', 'POST', $data);
}
public function deleteLicense($mid) {
$data = ['mid' => $mid];
return $this->request('/api/licenses/delete', 'DELETE', $data);
}
}
// Kullanım
$client = new MSCClient('your-api-key-here');
$result = $client->listLicenses();
print_r($result);
?>
🔒 Güvenlik Özellikleri
1. Uygulama Bütünlük Kontrolü
- Çalıştırılabilir dosyanın SHA256 hash'i kontrol edilir
.sha256
dosyası ile karşılaştırılır- Bütünlük ihlali durumunda sistem durdurulur
2. Sürekli Lisans Doğrulama
- Arka planda her saniye lisans sunucusu kontrol edilir
- DNS manipülasyonu ve IP değişiklikleri tespit edilir
- Güvenlik ihlali durumunda sistem otomatik olarak durdurulur
3. API Key Kimlik Doğrulama
- Tüm API endpointleri admin API key gerektirir
- 64 karakterlik rastgele API anahtarları
- Kullanıcı bazlı erişim kontrolü
4. IP Bazlı Lisanslama
- Lisanslar belirli IP adreslerine bağlıdır
- IP değişikliği durumunda lisans geçersiz hale gelir
🐛 Sorun Giderme
Yaygın Sorunlar
"Güvenlik ihlali" hatası
.sha256
dosyasının mevcut olduğundan emin olun- Çalıştırılabilir dosyanın değiştirilmediğini kontrol edin
"Lisans sunucusuna ulaşılamıyor"
- İnternet bağlantınızı kontrol edin
- DNS ayarlarınızı kontrol edin
- Firewall ayarlarını kontrol edin
"API anahtarı geçersiz"
- Doğru API anahtarını kullandığınızdan emin olun
- Admin kullanıcısı için API anahtarı oluşturun
Logları İzleme
# Logları dosyaya yönlendir
./msc start > msc.log 2>&1 &
# Logları canlı izle
tail -f msc.log
Magnesify Sovereign Cloud - Güvenli ve güvenilir lisans yönetimi