Skip to content

Documentation SDK Python

SDK Python async moderne pour l'API Sharokey avec nommage des méthodes cohérent avec le CLI. Parfait pour les applications Python, projets de science des données et scripts d'automatisation.

🚀 Démarrage Rapide

Installation

bash
pip install sharokey

Ou avec poetry :

bash
poetry add sharokey

Configuration de Base

python
import asyncio
import sharokey

async def main():
    # Initialiser le client (équivalent à : sharokey config --token xxx)
    client = sharokey.SharokeyClient('YOUR_API_KEY')
    
    # Tester la connexion
    await client.test_connection()
    print("Connecté avec succès !")

# Exécuter la fonction async
asyncio.run(main())

Premier Secret

python
import asyncio
import sharokey

async def create_first_secret():
    client = sharokey.SharokeyClient('YOUR_API_KEY')
    
    # Créer un secret simple (syntaxe style CLI)
    secret = await client.create(
        "Mon premier secret",  # contenu
        24,                    # heures
        1                      # vues
    )
    
    print(f"URL du Secret : {secret.share_url}")
    print(f"Slug du Secret : {secret.slug}")
    print(f"Expire le : {secret.expires_at}")

asyncio.run(create_first_secret())

⚙️ Configuration du Client

Options du Constructeur

python
import sharokey

# Configuration basique
client = sharokey.SharokeyClient('YOUR_API_KEY')

# Avec toutes les options
client = sharokey.SharokeyClient(
    token='YOUR_API_KEY',              # Requis : Token d'authentification API
    api_url="https://api.sharokey.com/api/v1", # Optionnel : URL API personnalisée
    timeout=30                           # Optionnel : Timeout des requêtes en secondes
)

🔐 Créer des Secrets

Création de Secret Basique

python
# Secret texte simple (équivalent CLI : sharokey create "contenu" --hours 24 --views 3)
secret = await client.create(
    "Mot de passe base de données : secret123",
    hours=24,
    views=3
)

print(f"URL de Partage : {secret.share_url}")

Avec Description et Protection

python
# Avec options de protection supplémentaires
secret = await client.create(
    "Données financières sensibles",
    hours=48,
    views=5,
    description="Accès rapport financier T4",
    password="ProtectionSupplementaire2024!",
    otp_email="[email protected]"
)

print(f"Secret créé avec protection par mot de passe et OTP")
print(f"URL de Partage : {secret.share_url}")
print(f"A un mot de passe : {secret.has_password}")
print(f"A un OTP : {secret.has_otp}")

Limitation OTP

Les OTP par email et SMS sont mutuellement exclusifs - vous ne pouvez en utiliser qu'un par secret.

Avec Pièces Jointes

Le SDK Python accepte les chemins de fichiers pour les pièces jointes :

python
# Pièce jointe unique
secret = await client.create(
    "Documents contractuels",
    hours=168,  # 1 semaine
    views=5,
    description="Documents légaux pour révision",
    attachments=["contrat.pdf"]
)

# Pièces jointes multiples
secret = await client.create(
    "Livrables du projet",
    hours=72,   # 3 jours
    views=3,
    description="Fichiers finaux du projet",
    attachments=[
        "specifications.docx",
        "wireframes.pdf", 
        "schema_base_donnees.sql"
    ]
)

print(f"Secret créé avec {secret.attachment_count} pièces jointes")

Limites des pièces jointes : 10 fichiers maximum, 10 Mo au total

Exemple de Protection Complète

python
# Toutes les options de protection
secret = await client.create(
    "Données de fusion hautement confidentielles",
    hours=72,
    views=2,
    description="Documents M&A pour révision du conseil",
    password="ConseilAdministration2024!",
    otp_email="[email protected]",
    attachments=[
        "term_sheet.pdf",
        "due_diligence.xlsx",
        "avis_juridique.docx"
    ]
)

print(f"Secret hautement protégé créé :")
print(f"- URL de Partage : {secret.share_url}")
print(f"- Expire : {secret.expires_at}")
print(f"- Vues max : {secret.maximum_views}")
print(f"- Pièces jointes : {secret.attachment_count}")
print(f"- A un mot de passe : {secret.has_password}")
print(f"- A un OTP : {secret.has_otp}")

📝 Gestion des Secrets

Lister les Secrets

python
# Listage basique (équivalent CLI : sharokey list)
secrets = await client.list()

for secret in secrets:
    print(f"{secret.slug}: {secret.description} ({secret.status})")

# Avec filtres et pagination
filtered_secrets = await client.list(
    limit=20,
    status='active',
    creator='[email protected]'
)

print(f"Trouvé {len(filtered_secrets)} secrets actifs")

Fonctionnalité de Recherche

python
# Rechercher dans les descriptions et le contenu
results = await client.list(status='active', limit=100)
search_term = "base de données"
matching_secrets = [s for s in results if search_term.lower() in (s.description or '').lower()]

print(f"Trouvé {len(matching_secrets)} secrets contenant '{search_term}'")

Détails d'un Secret

python
# Obtenir par slug (équivalent CLI : sharokey get ABC123)
secret = await client.get('ABC123XYZ')

print(f"Détails du secret :")
print(f"- Description : {secret.description}")
print(f"- Statut : {secret.status}")
print(f"- Créé : {secret.created_at}")
print(f"- Expire : {secret.expires_at}")
print(f"- Vues restantes : {secret.remaining_views}/{secret.maximum_views}")
print(f"- A un mot de passe : {secret.has_password}")
print(f"- A un OTP : {secret.has_otp}")
print(f"- Nombre de pièces jointes : {secret.attachment_count}")

Supprimer des Secrets

python
# Supprimer un secret unique (équivalent CLI : sharokey delete ABC123)
await client.delete('ABC123XYZ')
print("Secret supprimé avec succès")

# Supprimer plusieurs secrets
slugs_to_delete = ['ABC123', 'DEF456', 'GHI789']
for slug in slugs_to_delete:
    try:
        await client.delete(slug)
        print(f"Supprimé {slug}")
    except sharokey.NotFoundError:
        print(f"Secret {slug} non trouvé")

🔧 Fonctions Utilitaires

Génération de Mots de Passe

python
# Générer un mot de passe sécurisé (équivalent CLI : sharokey generate-password)
password = await client.generate_password()
print(f"Mot de passe généré : {password}")  # 16 caractères par défaut

# Longueur personnalisée (8-32 caractères)
long_password = await client.generate_password(length=24)
print(f"Mot de passe long : {long_password}")

# Générer un mot de passe et créer un secret en un appel
password_secret = await client.create_password(
    length=20,
    hours=24,
    views=1,
    description="Nouveau mot de passe admin",
    otp_email="[email protected]"
)

print(f"Mot de passe généré : {password_secret.generated_password}")
print(f"URL de Partage : {password_secret.share_url}")

Test de Connectivité

python
# Tester la connectivité API (équivalent CLI : sharokey test)
try:
    is_connected = await client.test_connection()
    if is_connected:
        print("✅ Connexion API réussie")
        
        # Obtenir des informations de connexion supplémentaires
        print(f"URL API : {client.api_url}")
        print(f"Token configuré : {'Oui' if client.token else 'Non'}")
except Exception as error:
    print(f"❌ Échec de connexion : {error}")

Statistiques

python
# Obtenir les statistiques du compte (équivalent CLI : sharokey stats)
stats = await client.stats()

print("📊 Statistiques du Compte :")
print(f"- Total des secrets : {stats.total_secrets}")
print(f"- Secrets actifs : {stats.active_secrets}")
print(f"- Total des vues : {stats.total_views}")
print(f"- Stockage utilisé : {stats.storage_used / 1024 / 1024:.1f} Mo")

📧 Demandes de Secret

Demander à d'autres personnes de partager des secrets avec vous de manière sécurisée via des URL de demande générées.

Créer une Demande de Secret

python
# Demande de secret de base
request = await client.create_request(
    message="Veuillez partager les identifiants de base de données",
    description="Accès DB de production nécessaire"
)

print(f"Demande créée : {request.url}")
print(f"Envoyez cette URL au destinataire : {request.url}")

# Avec temps d'expiration et limites de vues
request = await client.create_request(
    message="Partager config VPN",
    description="Configuration accès distant",
    secret_expiration_hours=24,  # Le secret expirera dans 24h
    request_expiration_hours=48, # La demande expire dans 48h
    maximum_views=1              # Le secret peut être vu une seule fois
)

# Avec livraison par email
request = await client.create_request(
    message="Veuillez fournir les clés API",
    description="Configuration intégration",
    email_to="[email protected]",
    email_reply="[email protected]"
)

# Exemple complet avec toutes les options
request = await client.create_request(
    message="Veuillez partager les identifiants de production de manière sécurisée",
    description="Accès déploiement Q4 nécessaire",
    secret_expiration_hours=24,
    request_expiration_hours=48,
    maximum_views=1,
    email_to="[email protected]",
    email_reply="[email protected]"
)

print(f"Demande complète créée : {request.url}")

Lister les Demandes de Secret

python
# Lister toutes les demandes
requests = await client.list_requests()

for req in requests:
    print(f"Demande {req.token}: {req.description}")
    print(f"  Statut: {req.status}")
    print(f"  Expire: {req.request_expiration}")

# Avec filtres
active_requests = await client.list_requests(status='active', limit=10)
print(f"Demandes actives : {len(active_requests)}")

# Filtrer par différents critères
recent_requests = await client.list_requests(
    status='active',
    limit=5
)

print(f"Trouvé {len(recent_requests)} demandes actives récentes")

Obtenir les Détails d'une Demande

python
# Obtenir les détails d'une demande spécifique par ID
request = await client.get_request(123)

print(f"Détails de la demande :")
print(f"- Message : {request.message}")
print(f"- Description : {request.description}")
print(f"- Statut : {request.status}")
print(f"- Créé : {request.created_at}")
print(f"- Expire : {request.request_expiration}")
print(f"- Email destinataire : {request.email_to}")
print(f"- URL : {request.url}")

Supprimer une Demande

python
# Supprimer et invalider une demande
try:
    await client.delete_request(123)
    print("Demande supprimée avec succès")
except Exception as e:
    print(f"Erreur lors de la suppression : {e}")

# Supprimer plusieurs demandes
request_ids = [123, 124, 125]
for req_id in request_ids:
    try:
        await client.delete_request(req_id)
        print(f"Demande {req_id} supprimée")
    except Exception as e:
        print(f"Erreur pour demande {req_id} : {e}")

Statistiques des Demandes

python
# Obtenir les statistiques de vos demandes de secret
stats = await client.request_stats()

print("📊 Statistiques des Demandes :")
print(f"- Total demandes : {stats.total_requests}")
print(f"- Demandes actives : {stats.active_requests}")
print(f"- Demandes expirées : {stats.expired_requests}")
print(f"- Créées aujourd'hui : {stats.requests_created_today}")
print(f"- Créées cette semaine : {stats.requests_created_this_week}")
print(f"- Créées ce mois : {stats.requests_created_this_month}")
print(f"- Temps de réponse moyen : {stats.average_response_time_hours:.1f} heures")

Fonctions Utilitaires pour les Demandes

python
# Vérifier le statut d'une demande
def check_request_status(request):
    """Vérifier si une demande est encore active"""
    if request.status == 'active':
        return True
    elif request.status == 'expired':
        return False
    else:
        return None

# Gérer les demandes par lot
async def manage_requests_batch():
    """Gérer plusieurs demandes en une seule opération"""
    
    # Obtenir toutes les demandes actives
    active_requests = await client.list_requests(status='active')
    
    print(f"Gestion de {len(active_requests)} demandes actives")
    
    for request in active_requests:
        print(f"Demande {request.id}:")
        print(f"  - Description: {request.description}")
        print(f"  - Expire: {request.request_expiration}")
        print(f"  - URL: {request.url}")
        
        # Exemple de logique métier
        if request.description and "urgent" in request.description.lower():
            print(f"  ⚠️  Demande urgente détectée!")

# Exemple d'utilisation
await manage_requests_batch()

🚨 Gestion d'Erreurs

Le SDK Python fournit des exceptions typées pour différents scénarios d'erreur :

Types d'Exceptions

python
import sharokey
from sharokey import (
    ValidationError,
    AuthenticationError,
    NotFoundError,
    AttachmentError,
    NetworkError
)

try:
    secret = await client.create(
        "Mon contenu secret",
        hours=24,
        views=1
    )
except AuthenticationError as e:
    print(f"Échec de l'authentification : {e}")
    # Gérer token invalide ou expiré
except ValidationError as e:
    print(f"Erreur de validation : {e}")
    # Gérer paramètres invalides (heures, vues, etc.)
except AttachmentError as e:
    print(f"Erreur de pièce jointe : {e}")
    # Gérer limitations de taille/nombre de fichiers
except NetworkError as e:
    print(f"Erreur réseau : {e}")
    # Gérer problèmes de connexion
except Exception as e:
    print(f"Erreur inattendue : {e}")

Scénarios d'Erreur Spécifiques

python
# Erreurs de pièces jointes
try:
    await client.create(
        "Test de gros fichier",
        hours=24,
        views=1,
        attachments=["fichier_enorme.zip"]  # > 10Mo
    )
except AttachmentError as e:
    print(f"Fichier trop volumineux : {e}")

# Trop de pièces jointes
try:
    many_files = [f"fichier_{i}.txt" for i in range(15)]  # Plus de 10 fichiers
    await client.create(
        "Fichiers multiples",
        hours=24,
        views=1,
        attachments=many_files
    )
except AttachmentError as e:
    print(f"Trop de fichiers : {e}")

# Temps d'expiration invalide
try:
    await client.create(
        "Expiration invalide",
        hours=10000,  # > 1000 heures
        views=1
    )
except ValidationError as e:
    print(f"Heures invalides : {e}")

🔐 Fonctionnalités de Sécurité

Chiffrement Zero Knowledge

Tous les secrets utilisent un chiffrement côté client identique aux autres librairies :

  • Algorithme : AES-GCM-256
  • Dérivation de Clé : PBKDF2 avec 10 000 itérations
  • Système à deux clés : CléA (serveur) + CléB (fragment URL de partage)
  • Perfect Forward Secrecy : Chaque secret utilise des clés de chiffrement uniques

Bonnes Pratiques de Sécurité

python
import os
import getpass

# Gestion sécurisée des tokens
def get_api_token():
    """Obtenir le token API depuis l'environnement ou demander de manière sécurisée"""
    token = os.environ.get('SHAROKEY_TOKEN')
    if not token:
        token = getpass.getpass('Entrez le token API Sharokey : ')
    return token

# Utiliser le chargement sécurisé de token
client = sharokey.SharokeyClient(token=get_api_token())

# Gestion sécurisée des fichiers
import stat

def create_secure_secret_with_file(filepath, hours=24, views=1):
    """Créer un secret avec fichier, en s'assurant des permissions sécurisées"""
    
    # Vérifier les permissions du fichier
    file_stat = os.stat(filepath)
    if file_stat.st_mode & stat.S_IROTH:  # Lisible par tous
        print(f"Attention : {filepath} est lisible par tous")
    
    # Créer le secret
    return await client.create(
        f"Fichier confidentiel : {os.path.basename(filepath)}",
        hours=hours,
        views=views,
        attachments=[filepath]
    )

🛠️ Exemples d'Intégration

Intégration Django

python
# views.py
from django.http import JsonResponse
import json
import asyncio
import sharokey

# Configurer le client
client = sharokey.SharokeyClient('YOUR_API_KEY')

async def create_secret_api(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            
            secret = await client.create(
                data['content'],
                hours=data.get('hours', 24),
                views=data.get('views', 1),
                description=data.get('description'),
                password=data.get('password')
            )
            
            return JsonResponse({
                'success': True,
                'share_url': secret.share_url,
                'slug': secret.slug,
                'expires_at': secret.expires_at
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            }, status=400)
    
    return JsonResponse({'error': 'Méthode non autorisée'}, status=405)

Intégration FastAPI

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import sharokey

app = FastAPI()
client = sharokey.SharokeyClient('YOUR_API_KEY')

class SecretRequest(BaseModel):
    content: str
    hours: int = 24
    views: int = 1
    description: str = None
    password: str = None
    otp_email: str = None

@app.post("/secrets")
async def create_secret(request: SecretRequest):
    try:
        secret = await client.create(
            request.content,
            hours=request.hours,
            views=request.views,
            description=request.description,
            password=request.password,
            otp_email=request.otp_email
        )
        
        return {
            "slug": secret.slug,
            "share_url": secret.share_url,
            "expires_at": secret.expires_at,
            "maximum_views": secret.maximum_views
        }
        
    except sharokey.ValidationError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except sharokey.AuthenticationError as e:
        raise HTTPException(status_code=401, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/secrets")
async def list_secrets(limit: int = 20, status: str = None):
    try:
        secrets = await client.list(limit=limit, status=status)
        return [
            {
                "slug": s.slug,
                "description": s.description,
                "status": s.status,
                "remaining_views": s.remaining_views,
                "maximum_views": s.maximum_views,
                "expires_at": s.expires_at
            }
            for s in secrets
        ]
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

Intégration Science des Données

python
import pandas as pd
import asyncio
import sharokey

async def share_analysis_results():
    """Partager les résultats d'analyse de données de manière sécurisée"""
    
    client = sharokey.SharokeyClient('YOUR_API_KEY')
    
    # Sauvegarder les résultats d'analyse dans des fichiers
    df = pd.read_csv('donnees.csv')
    analysis_results = df.describe()
    
    # Sauvegarder dans des fichiers temporaires
    analysis_results.to_csv('resume_analyse.csv')
    df.head(100).to_csv('echantillon_donnees.csv')
    
    # Créer des graphiques
    import matplotlib.pyplot as plt
    plt.figure(figsize=(10, 6))
    df.hist()
    plt.savefig('distribution_donnees.png')
    plt.close()
    
    # Partager les résultats de manière sécurisée
    secret = await client.create(
        "Résultats d'analyse de données pour T4 2024",
        hours=48,
        views=5,
        description="Analyse statistique et données d'échantillon",
        password="AnalyseDonnees2024!",
        attachments=[
            'resume_analyse.csv',
            'echantillon_donnees.csv', 
            'distribution_donnees.png'
        ]
    )
    
    print(f"Résultats d'analyse partagés : {secret.share_url}")
    
    # Nettoyer les fichiers temporaires
    import os
    for file in ['resume_analyse.csv', 'echantillon_donnees.csv', 'distribution_donnees.png']:
        os.remove(file)
    
    return secret.share_url

# Exécuter l'analyse
asyncio.run(share_analysis_results())

Script d'Automatisation

python
#!/usr/bin/env python3
"""
Script de gestion automatisée des secrets
"""
import asyncio
import argparse
import sys
import sharokey

async def main():
    parser = argparse.ArgumentParser(description='Script d\'automatisation Sharokey')
    parser.add_argument('action', choices=['create', 'list', 'delete', 'cleanup'])
    parser.add_argument('--content', help='Contenu du secret')
    parser.add_argument('--hours', type=int, default=24, help='Heures d\'expiration')
    parser.add_argument('--views', type=int, default=1, help='Vues maximum')
    parser.add_argument('--slug', help='Slug du secret pour opérations get/delete')
    parser.add_argument('--token', help='Token API')
    
    args = parser.parse_args()
    
    # Initialiser le client
    client = sharokey.SharokeyClient(args.token or 'YOUR_API_KEY')
    
    if args.action == 'create':
        if not args.content:
            print("Erreur : --content est requis pour l'action create")
            sys.exit(1)
            
        secret = await client.create(
            args.content,
            hours=args.hours,
            views=args.views
        )
        print(f"Créé : {secret.share_url}")
        
    elif args.action == 'list':
        secrets = await client.list(limit=50)
        print(f"{'Slug':<12} {'Statut':<10} {'Vues':<8} {'Description'}")
        print("-" * 60)
        for secret in secrets:
            views = f"{secret.remaining_views}/{secret.maximum_views}"
            desc = (secret.description or "Aucune description")[:30]
            print(f"{secret.slug:<12} {secret.status:<10} {views:<8} {desc}")
            
    elif args.action == 'delete':
        if not args.slug:
            print("Erreur : --slug est requis pour l'action delete")
            sys.exit(1)
            
        await client.delete(args.slug)
        print(f"Supprimé : {args.slug}")
        
    elif args.action == 'cleanup':
        # Supprimer les secrets expirés
        secrets = await client.list(limit=100)
        expired_secrets = [s for s in secrets if s.status == 'expired']
        
        print(f"Trouvé {len(expired_secrets)} secrets expirés")
        for secret in expired_secrets:
            await client.delete(secret.slug)
            print(f"Supprimé le secret expiré : {secret.slug}")

if __name__ == '__main__':
    asyncio.run(main())

📏 Cohérence des Méthodes

Le SDK Python maintient des noms de méthodes cohérents avec le CLI :

Commande CLIMéthode PythonDescription
sharokey config --token xxxSharokeyClient('YOUR_API_KEY')Configuration
sharokey createclient.create()Créer un secret
sharokey listclient.list()Lister les secrets
sharokey get SLUGclient.get(slug)Détails d'un secret
sharokey delete SLUGclient.delete(slug)Supprimer un secret
sharokey statsclient.stats()Obtenir les statistiques
sharokey generate-passwordclient.generate_password()Générer un mot de passe
sharokey testclient.test_connection()Tester la connectivité

🔗 Ressources Associées

📜 License

Le SDK Python Sharokey est distribué sous la Licence MIT.
Voir LICENSE pour plus de détails.

Released under the MIT License.