docs: Add module guide dan security guidelines untuk API documentation

This commit is contained in:
mwpn
2025-12-17 11:11:26 +07:00
parent c7bfaee618
commit 220b554a17
3 changed files with 323 additions and 7 deletions

111
MODULE_GUIDE.md Normal file
View File

@@ -0,0 +1,111 @@
# Panduan Menambah Module Baru
## 📦 Struktur Module
Setiap module baru mengikuti pola yang sama:
```
src/Modules/ModuleBaru/
├── ModuleBaruRoutes.php # Register routes
├── Controller.php # Request handler
└── Service.php # Business logic
```
## 🚀 Langkah Menambah Module
### 1. Buat Struktur Folder
```bash
mkdir -p src/Modules/ModuleBaru
```
### 2. Buat Routes File
`src/Modules/ModuleBaru/ModuleBaruRoutes.php`:
```php
<?php
declare(strict_types=1);
namespace App\Modules\ModuleBaru;
use Slim\App;
class ModuleBaruRoutes
{
public static function register(App $app): void
{
$app->group('/modulebaru', function ($group) {
$group->group('/v1', function ($v1Group) {
// Routes di sini
$v1Group->get('/endpoint', [Controller::class, 'method']);
});
});
}
}
```
### 3. Register di public/index.php
Tambahkan di bagian "Register module routes":
```php
use App\Modules\ModuleBaru\ModuleBaruRoutes;
// ...
// Register module routes
HealthRoutes::register($app);
AuthRoutes::register($app);
RetribusiRoutes::register($app);
ModuleBaruRoutes::register($app); // <-- Tambahkan di sini
```
### 4. Update OpenAPI Spec (Opsional)
Edit `public/docs/openapi.json` dan tambahkan endpoint baru di `paths`.
## ✅ Contoh: Module "Parkir"
```php
// src/Modules/Parkir/ParkirRoutes.php
namespace App\Modules\Parkir;
use App\Middleware\JwtMiddleware;
use Slim\App;
class ParkirRoutes
{
public static function register(App $app): void
{
$jwtMiddleware = new JwtMiddleware();
$app->group('/parkir', function ($group) use ($jwtMiddleware) {
$group->group('/v1', function ($v1Group) use ($jwtMiddleware) {
$v1Group->get('/zones', [ParkirController::class, 'getZones'])
->add($jwtMiddleware);
});
});
}
}
```
## 🔄 Best Practices
1. **Isolasi**: Setiap module independen
2. **Naming**: Gunakan namespace yang jelas
3. **Routes**: Group by module name
4. **Versioning**: Gunakan `/v1` untuk future compatibility
5. **Middleware**: Apply di level group atau route
## 📝 Checklist Module Baru
- [ ] Buat folder `src/Modules/ModuleName/`
- [ ] Buat `ModuleNameRoutes.php` dengan method `register()`
- [ ] Buat Controller & Service (jika perlu)
- [ ] Register di `public/index.php`
- [ ] Test routes
- [ ] Update OpenAPI spec (opsional)
- [ ] Commit & push

204
SECURITY.md Normal file
View File

@@ -0,0 +1,204 @@
# Security Guidelines - API Documentation
## 🔒 Keamanan API Documentation
### Current Implementation
Saat ini API documentation (Swagger UI) di `/docs` **PUBLIC** - bisa diakses tanpa authentication.
### ⚠️ Security Considerations
**Risiko jika docs public:**
1. **Information Disclosure**: Endpoint structure terlihat semua orang
2. **Attack Surface**: Attacker tahu semua endpoint yang ada
3. **API Key Exposure**: Jika ada contoh API key di docs (jangan!)
4. **Business Logic**: Flow bisnis bisa terlihat
**Tapi juga ada benefit:**
1. **Developer Experience**: Developer mudah test API
2. **Onboarding**: New developer cepat paham
3. **Integration**: Partner bisa lihat spec dengan mudah
## 🛡️ Opsi Security untuk Docs
### Opsi 1: Public (Current - Recommended untuk Internal API)
**Cocok untuk:**
- Internal API (tidak public internet)
- API dengan authentication kuat (JWT + Role)
- Development/Staging environment
**Kelebihan:**
- Mudah digunakan
- Developer friendly
- Tidak perlu setup tambahan
**Kekurangan:**
- Endpoint structure terlihat
- Perlu pastikan tidak ada sensitive info di docs
### Opsi 2: JWT Protected (Recommended untuk Production)
Protect `/docs` dengan JWT middleware.
**Implementasi:**
Update `public/index.php`:
```php
use App\Middleware\JwtMiddleware;
// ...
// Docs route - dengan JWT protection
$jwtMiddleware = new JwtMiddleware();
$app->get('/docs', function ($request, $response) {
// ... existing code ...
})->add($jwtMiddleware);
$app->get('/docs/openapi.json', function ($request, $response) {
// ... existing code ...
})->add($jwtMiddleware);
```
**Cocok untuk:**
- Production API yang sensitive
- Public API dengan authentication
- API yang perlu kontrol akses
### Opsi 3: IP Whitelist (Paling Ketat)
Hanya allow IP tertentu yang bisa akses docs.
**Implementasi:**
Buat middleware `src/Middleware/IpWhitelistMiddleware.php`:
```php
<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Config\AppConfig;
use App\Support\ResponseHelper;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Psr7\Factory\ResponseFactory;
class IpWhitelistMiddleware implements MiddlewareInterface
{
private array $allowedIps;
public function __construct(array $allowedIps)
{
$this->allowedIps = $allowedIps;
}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$serverParams = $request->getServerParams();
$clientIp = $serverParams['REMOTE_ADDR'] ?? '0.0.0.0';
// Check X-Forwarded-For (behind proxy)
if (isset($serverParams['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $serverParams['HTTP_X_FORWARDED_FOR']);
$clientIp = trim($ips[0]);
}
if (!in_array($clientIp, $this->allowedIps, true)) {
$responseFactory = new ResponseFactory();
$response = $responseFactory->createResponse();
return ResponseHelper::json(
$response,
['error' => 'forbidden', 'message' => 'Access denied'],
403
);
}
return $handler->handle($request);
}
}
```
Gunakan di `public/index.php`:
```php
use App\Middleware\IpWhitelistMiddleware;
use App\Config\AppConfig;
// Get allowed IPs from ENV
$allowedIps = explode(',', AppConfig::get('DOCS_ALLOWED_IPS', ''));
$ipWhitelist = new IpWhitelistMiddleware($allowedIps);
$app->get('/docs', function ($request, $response) {
// ... existing code ...
})->add($ipWhitelist);
```
**Cocok untuk:**
- Very sensitive API
- Internal company network only
- High security requirement
### Opsi 4: Basic Auth (Simple)
Protect dengan HTTP Basic Authentication.
**Implementasi:**
Buat middleware atau gunakan nginx basic auth:
```nginx
location /docs {
auth_basic "API Documentation";
auth_basic_user_file /path/to/.htpasswd;
# ... rest of config
}
```
## 📋 Recommendations
### Untuk API Internal (Current Setup)
**Status**: ✅ **AMAN** jika:
- API hanya diakses dari internal network
- Semua endpoint sudah protected dengan JWT/API Key
- Tidak ada sensitive data di OpenAPI spec
- Server tidak exposed ke public internet
**Action**:
- Pastikan tidak ada contoh API key/password di docs
- Review OpenAPI spec sebelum deploy
- Monitor access logs
### Untuk Public API
**Status**: ⚠️ **PERLU PROTECTION** jika:
- API exposed ke public internet
- Ada sensitive business logic
- Compliance requirement (GDPR, dll)
**Action**:
- Implement JWT protection untuk `/docs`
- Atau IP whitelist untuk internal team
- Review dan sanitize OpenAPI spec
## 🔐 Best Practices
1. **Jangan hardcode credentials** di OpenAPI spec
2. **Gunakan environment variables** untuk examples
3. **Review secara berkala** endpoint yang di-expose
4. **Monitor access logs** untuk `/docs`
5. **Update docs** jika ada perubahan security
## 🚨 Jika Perlu Protect Docs Sekarang
Saya bisa implement JWT protection untuk `/docs` dengan cepat. Tinggal kasih tahu mau pakai opsi mana!

View File

@@ -27,6 +27,7 @@ $app->get('/', function ($request, $response) {
}); });
// Docs route - serve Swagger UI // Docs route - serve Swagger UI
// NOTE: Saat ini PUBLIC. Jika perlu protect, tambahkan JwtMiddleware atau IpWhitelistMiddleware
$app->get('/docs', function ($request, $response) { $app->get('/docs', function ($request, $response) {
$docsPath = __DIR__ . '/docs/index.html'; $docsPath = __DIR__ . '/docs/index.html';
@@ -44,6 +45,7 @@ $app->get('/docs', function ($request, $response) {
}); });
// Serve OpenAPI JSON // Serve OpenAPI JSON
// NOTE: Saat ini PUBLIC. Jika perlu protect, tambahkan middleware
$app->get('/docs/openapi.json', function ($request, $response) { $app->get('/docs/openapi.json', function ($request, $response) {
$openApiPath = __DIR__ . '/docs/openapi.json'; $openApiPath = __DIR__ . '/docs/openapi.json';
@@ -70,4 +72,3 @@ RealtimeRoutes::register($app);
// Run application // Run application
$app->run(); $app->run();