API anahtarını depodan çıkarmanın en temiz yolu, onu HashiCorp Vault'a koyup çalışma zamanında okumaktır: anahtar şifreli durur, her okuma kimlikle birlikte denetim kaydına düşer ve anahtarı değiştirmek için tek bir servisi yeniden dağıtmanız gerekmez. Bu rehber, CaptchaAI API anahtarınızı Vault'ta saklamayı, çözüm çalışanlarına salt okunur bir politikayla vermeyi ve kesintisiz döndürmeyi anlatır.
Anahtarın .env dosyasında durduğu bir kurulum, üç kişilik bir ekipte sorun çıkarmaz. Sekiz geliştiricinin aynı müşteri otomasyonuna dokunduğu, anahtarın bir kez Slack'te paylaşıldıktan sonra kimde olduğunun bilinmediği bir kurulumda çıkarır. Vault'un çözdüğü sorun tam olarak budur.
Vault ile .env arasındaki fark
.env ile |
Vault ile |
|---|---|
| API anahtarı dosyada veya kodda düz metin | Anahtar Vault'ta şifreli saklanır |
| Anahtar Slack veya e-posta ile paylaşılır | Erişim, kimliği doğrulanmış API üzerinden |
| Kimin ne zaman okuduğu bilinmez | Her okuma kimlikle günlüğe yazılır |
| Anahtar değişimi elle ve dağıtımla | Dağıtım gerektirmeyen rotasyon |
| Tüm ortamlarda tek anahtar | Ortam başına ayrı anahtar ve politika |
Pratik kazanç şu: anahtarı değiştirmek artık bir kod değişikliği değil, tek bir Vault yazma işlemi.
Başlamadan önce gerekenler
- HashiCorp Vault sunucusu (kendi sunucunuzda veya HCP Vault üzerinde)
- Vault CLI veya HTTP API erişimi
- Bir CaptchaAI API anahtarı (hesap panelinden birkaç dakikada alınır)
- Python 3.8+ veya Node.js 18+
Adım 1: Anahtarı Vault'a yazın
KV v2 gizli motorunu açın ve anahtarı tek bir yola koyun:
# Enable the KV secrets engine (if not already enabled)
vault secrets enable -path=secret kv-v2
# Store the CaptchaAI API key
vault kv put secret/captchaai api_key="YOUR_API_KEY"
# Verify
vault kv get secret/captchaai
Bu noktadan sonra anahtarın tek doğru kopyası Vault'tadır; depodaki her kopya silinmelidir.
Adım 2: Çalışanlara salt okunur politika verin
Çözüm çalışanının yazma yetkisine ihtiyacı yok, yalnızca okumaya:
# captcha-worker-policy.hcl
path "secret/data/captchaai" {
capabilities = ["read"]
}
path "secret/metadata/captchaai" {
capabilities = ["read"]
}
Politikayı uygulayın:
vault policy write captcha-worker captcha-worker-policy.hcl
Ortamları ayırmak isterseniz aynı politikayı secret/data/captchaai/prod ve secret/data/captchaai/staging yolları için ayrı ayrı tanımlayın — üretim anahtarının test iş yüklerine sızmaması için en ucuz önlem budur.
Adım 3: Python tarafında anahtarı okuyun ve görevi gönderin
Aşağıdaki sınıf anahtarı Vault'tan alır, bellekte tutar ve saatte bir tazeler. in.php'ye görevi gönderip res.php'yi sorgulayan akış, standart reCAPTCHA v2 çözüm akışının aynısıdır; tek fark, anahtarın nereden geldiğidir.
# vault_solver.py
import os
import time
import hvac
import requests
# Connect to Vault
vault_client = hvac.Client(
url=os.environ.get("VAULT_ADDR", "http://127.0.0.1:8200"),
token=os.environ.get("VAULT_TOKEN"),
)
def get_api_key():
"""Retrieve CaptchaAI API key from Vault."""
secret = vault_client.secrets.kv.v2.read_secret_version(
path="captchaai",
mount_point="secret",
)
return secret["data"]["data"]["api_key"]
class CaptchaSolver:
"""CAPTCHA solver with Vault-managed credentials."""
def __init__(self):
self.api_key = get_api_key()
self.session = requests.Session()
self._key_fetched_at = time.time()
self._key_refresh_interval = 3600 # Re-fetch key hourly
def _refresh_key_if_needed(self):
"""Periodically refresh the key from Vault."""
if time.time() - self._key_fetched_at > self._key_refresh_interval:
self.api_key = get_api_key()
self._key_fetched_at = time.time()
def solve(self, sitekey, pageurl):
"""Solve reCAPTCHA v2 using Vault-managed key."""
self._refresh_key_if_needed()
# Submit
resp = self.session.get("https://ocr.captchaai.com/in.php", params={
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": "1",
})
result = resp.json()
if result.get("status") != 1:
raise Exception(f"Submit failed: {result.get('request')}")
task_id = result["request"]
time.sleep(15)
for _ in range(25):
poll = self.session.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": "1",
})
poll_result = poll.json()
if poll_result.get("status") == 1:
return poll_result["request"]
if poll_result.get("request") != "CAPCHA_NOT_READY":
raise Exception(f"Error: {poll_result.get('request')}")
time.sleep(5)
raise Exception("Timeout")
# Usage
solver = CaptchaSolver()
token = solver.solve(
"6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"https://www.google.com/recaptcha/api2/demo"
)
print(f"Token: {token[:30]}...")
Dikkat edilecek nokta _refresh_key_if_needed metodudur: anahtar her istekte değil, aralık dolduğunda yeniden okunur. Böylece Vault'a gereksiz yük binmeden rotasyon birkaç dakika içinde yakalanır.
Adım 4: Node.js tarafında aynı deseni kurun
Node.js çalışanlarında mantık birebir aynıdır — Vault'un HTTP API'sine X-Vault-Token başlığıyla gidilir, dönen data.data.api_key bellekte tutulur:
// vault_solver.js
const axios = require('axios');
const VAULT_ADDR = process.env.VAULT_ADDR || 'http://127.0.0.1:8200';
const VAULT_TOKEN = process.env.VAULT_TOKEN;
async function getApiKey() {
const resp = await axios.get(
`${VAULT_ADDR}/v1/secret/data/captchaai`,
{ headers: { 'X-Vault-Token': VAULT_TOKEN } }
);
return resp.data.data.data.api_key;
}
class CaptchaSolver {
constructor() {
this.apiKey = null;
this.keyFetchedAt = 0;
this.refreshInterval = 3600000; // 1 hour
}
async init() {
this.apiKey = await getApiKey();
this.keyFetchedAt = Date.now();
}
async refreshKeyIfNeeded() {
if (Date.now() - this.keyFetchedAt > this.refreshInterval) {
this.apiKey = await getApiKey();
this.keyFetchedAt = Date.now();
}
}
async solve(sitekey, pageurl) {
await this.refreshKeyIfNeeded();
const submit = await axios.get('https://ocr.captchaai.com/in.php', {
params: {
key: this.apiKey, method: 'userrecaptcha',
googlekey: sitekey, pageurl, json: '1',
},
});
if (submit.data.status !== 1) throw new Error(submit.data.request);
const taskId = submit.data.request;
await new Promise(r => setTimeout(r, 15000));
for (let i = 0; i < 25; i++) {
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: this.apiKey, action: 'get', id: taskId, json: '1' },
});
if (poll.data.status === 1) return poll.data.request;
if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
await new Promise(r => setTimeout(r, 5000));
}
throw new Error('Timeout');
}
}
(async () => {
const solver = new CaptchaSolver();
await solver.init();
const token = await solver.solve(
'6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
'https://www.google.com/recaptcha/api2/demo'
);
console.log(`Token: ${token.slice(0, 30)}...`);
})();
Aynı desen Cloudflare Turnstile ve GeeTest v3 çözümleri için de geçerlidir; değişen tek şey method parametresidir, anahtar yönetimi katmanı sabit kalır.
Kimlik doğrulama yöntemini iş yükünüze göre seçin
| Yöntem | Nerede uygun | Kurulum |
|---|---|---|
| Token | Geliştirme, CI/CD | VAULT_TOKEN ortam değişkeni |
| AppRole | Üretimdeki servisler | Role ID + Secret ID |
| Kubernetes | Kubernetes iş yükleri | Service account JWT |
| AWS IAM | EC2/Lambda çalışanları | Instance role |
Üretimde statik VAULT_TOKEN kullanmayın. AppRole ile çalışan, kendi kısa ömürlü token'ını alır:
# AppRole authentication — no static token needed
vault_client = hvac.Client(url=os.environ["VAULT_ADDR"])
vault_client.auth.approle.login(
role_id=os.environ["VAULT_ROLE_ID"],
secret_id=os.environ["VAULT_SECRET_ID"],
)
# Now read the secret
secret = vault_client.secrets.kv.v2.read_secret_version(path="captchaai")
api_key = secret["data"]["data"]["api_key"]
Anahtarı dağıtım yapmadan döndürün
- CaptchaAI kontrol panelinde yeni bir API anahtarı üretin
- Vault'u güncelleyin:
vault kv put secret/captchaai api_key="NEW_KEY" - Çalışanlar bir sonraki yenileme döngüsünde yeni anahtarı kendiliğinden alır
- Tüm çalışanlar yenilendikten sonra eski anahtarı panelden iptal edin
Kod değişikliği yok, dağıtım yok, bakım penceresi yok. Rotasyonu üç ayda bir tekrarlanan düzenli bir bakım işine çevirmek, anahtarın ömrünü kısaltmanın en kolay yoludur.
Türkiye'deki ekipler için pratik bir senaryo
E-ticaret ve fintech tarafında çalışan ajanslar tipik olarak birden çok müşteri için aynı otomasyon iskeletini kullanır. Her müşteri için ayrı bir Vault yolu (secret/captchaai/musteri-a, secret/captchaai/musteri-b) ve ayrı bir AppRole tanımladığınızda, bir müşterinin anahtarı diğerinin iş yüküne erişemez; sözleşme bittiğinde ilgili AppRole'u iptal etmeniz yeterlidir.
İki nokta ayrıca önemli. Birincisi, Vault'un denetim günlüğü, kişisel veri işleyen doğrulama ve veri toplama akışlarında KVKK kapsamındaki "kim, ne zaman erişti" sorusuna somut yanıt üretir. İkincisi, faturalama tarafında CaptchaAI planları thread bazlıdır — BASIC ($15/ay, 5 thread) ile başlayıp ADVANCE ($90/ay, 50 thread) veya PREMIUM ($170/ay, 100 thread) seviyesine geçebilirsiniz. Fiyatlar USD üzerindendir; anahtarı Vault'a taşımak maliyeti değiştirmez, yalnızca anahtarın kimde olduğunu bilinir kılar.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
Vault'tan 403 Forbidden |
Politika okumaya izin vermiyor | captcha-worker-policy.hcl içindeki yolu doğrulayın |
VAULT_TOKEN süresi doldu |
Token TTL'si aşıldı | Kendini yenileyebilen token'lar için AppRole'a geçin |
| Anahtar tazelenmiyor | Yenileme aralığı fazla uzun | _key_refresh_interval değerini düşürün |
| Vault'a ulaşılamıyor | Ağ veya sunucu sorunu | Anahtarı bellekte önbelleğe alıp geri dönüş kurgulayın |
CAPCHA_NOT_READY dönüp duruyor |
Görev henüz tamamlanmadı | Sorgulama aralığını koruyun; bu bir hata değildir |
Sık sorulan sorular
Vault'a erişemediğimde çözüm hattı duruyor mu?
Hayır — anahtarı ilk okuduğunuzda bellekte tuttuğunuz sürece durmaz. Yenileme anında Vault yanıt vermezse önbellekteki anahtarla devam edin, hatayı günlüğe yazın ve bir sonraki döngüde yeniden deneyin.
Anahtarı ne sıklıkla yeniden okumalıyım?
Örnekteki 3.600 saniyelik aralık çoğu üretim yükü için makul bir başlangıçtır. Rotasyonu daha hızlı yakalamak isterseniz 300–600 saniyeye indirin; her istekte okumak Vault'a gereksiz trafik bindirir.
AppRole'un Role ID ve Secret ID değerlerini nerede tutmalıyım?
Role ID'yi yapılandırmayla dağıtabilirsiniz. Secret ID ise kısa ömürlü olmalı ve CI/CD ya da orkestratör tarafından çalışma anında enjekte edilmelidir. İkisini birden imaja gömmek, kaçındığınız sorunu geri getirir.
Vault yerine AWS Secrets Manager veya Kubernetes Secrets kullanabilir miyim?
Evet. Desen değişmez: sırrı çalışma zamanında okuyun, bellekte tutun, periyodik olarak tazeleyin. AWS tarafında boto3 ile Secrets Manager'dan, Kubernetes tarafında service account JWT ile Vault'tan okursunuz; sabit kodlanmış anahtar bulundurmama ilkesi aynı kalır.
Vault'a geçtikten sonra eski anahtarı ne zaman iptal etmeliyim?
En uzun yenileme aralığınız kadar bekleyin. Örnekteki 3.600 saniyelik aralıkta bir saat sonra tüm çalışanlar yeni anahtarı almış olur; denetim günlüğünde eski anahtarla okuma kalmadığını görünce panelden iptal edin.
İlgili Makaleler
- IP beyaz listesiyle API anahtarı güvenliği
- CaptchaAI API anahtarı rotasyonu
- Google Cloud Functions ile CaptchaAI entegrasyonu
Sonraki Adımlar
Anahtarı depodan çıkarın, Vault'a koyun ve ilk çözümü bugün gönderin — API anahtarınızı alın.
İlgili kılavuzlar: