Integrations

CaptchaAI API Anahtar Yönetimi için Vault Entegrasyonu

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

  1. CaptchaAI kontrol panelinde yeni bir API anahtarı üretin
  2. Vault'u güncelleyin: vault kv put secret/captchaai api_key="NEW_KEY"
  3. Çalışanlar bir sonraki yenileme döngüsünde yeni anahtarı kendiliğinden alır
  4. 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

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:

Bu makale için yorumlar devre dışı bırakılmıştır.