gamma-security-basics

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Gamma Security Basics

Gamma 安全基础

Overview

概述

Security best practices for Gamma API integration to protect credentials and data.
为Gamma API集成制定的安全最佳实践,用于保护凭证和数据。

Prerequisites

前提条件

  • Active Gamma integration
  • Environment variable support
  • Understanding of secret management
  • 已激活Gamma集成
  • 支持环境变量
  • 了解密钥管理相关知识

Instructions

操作步骤

Step 1: Secure API Key Storage

步骤1:安全存储API密钥

typescript
// NEVER do this
const gamma = new GammaClient({
  apiKey: 'gamma_live_abc123...', // Hardcoded - BAD!
});

// DO this instead
const gamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY,
});
Environment Setup:
bash
undefined
typescript
// 绝对不要这么做
const gamma = new GammaClient({
  apiKey: 'gamma_live_abc123...', // 硬编码 - 错误做法!
});

// 正确做法如下
const gamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY,
});
环境设置:
bash
undefined

.env (add to .gitignore!)

.env(添加到.gitignore中!)

GAMMA_API_KEY=gamma_live_abc123...
GAMMA_API_KEY=gamma_live_abc123...

Load in application

在应用中加载

import 'dotenv/config';
undefined
import 'dotenv/config';
undefined

Step 2: Key Rotation Strategy

步骤2:密钥轮换策略

typescript
// Support multiple keys for rotation
const gamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_PRIMARY
    || process.env.GAMMA_API_KEY_SECONDARY,
});

// Rotation script
async function rotateApiKey() {
  // 1. Generate new key in Gamma dashboard
  // 2. Update GAMMA_API_KEY_SECONDARY
  // 3. Deploy and verify
  // 4. Swap PRIMARY and SECONDARY
  // 5. Revoke old key
}
typescript
// 支持多密钥轮换
const gamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_PRIMARY
    || process.env.GAMMA_API_KEY_SECONDARY,
});

// 轮换脚本
async function rotateApiKey() {
  // 1. 在Gamma控制台生成新密钥
  // 2. 更新GAMMA_API_KEY_SECONDARY
  // 3. 部署并验证
  // 4. 交换主密钥和备用密钥
  // 5. 吊销旧密钥
}

Step 3: Request Signing (if supported)

步骤3:请求签名(如支持)

typescript
import crypto from 'crypto';

function signRequest(payload: object, secret: string): string {
  const timestamp = Date.now().toString();
  const message = timestamp + JSON.stringify(payload);

  return crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
}

// Usage with webhook verification
function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
typescript
import crypto from 'crypto';

function signRequest(payload: object, secret: string): string {
  const timestamp = Date.now().toString();
  const message = timestamp + JSON.stringify(payload);

  return crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
}

// 用于Webhook验证
function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Step 4: Access Control Patterns

步骤4:访问控制模式

typescript
// Scoped API keys (if supported)
const readOnlyGamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_READONLY,
  scopes: ['presentations:read', 'exports:read'],
});

const fullAccessGamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_FULL,
});

// Permission check before operations
async function createPresentation(user: User, data: object) {
  if (!user.permissions.includes('gamma:create')) {
    throw new Error('Insufficient permissions');
  }
  return fullAccessGamma.presentations.create(data);
}
typescript
// 限定范围的API密钥(如支持)
const readOnlyGamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_READONLY,
  scopes: ['presentations:read', 'exports:read'],
});

const fullAccessGamma = new GammaClient({
  apiKey: process.env.GAMMA_API_KEY_FULL,
});

// 操作前检查权限
async function createPresentation(user: User, data: object) {
  if (!user.permissions.includes('gamma:create')) {
    throw new Error('权限不足');
  }
  return fullAccessGamma.presentations.create(data);
}

Step 5: Audit Logging

步骤5:审计日志

typescript
import { GammaClient } from '@gamma/sdk';

function createAuditedClient(userId: string) {
  return new GammaClient({
    apiKey: process.env.GAMMA_API_KEY,
    interceptors: {
      request: (config) => {
        console.log(JSON.stringify({
          timestamp: new Date().toISOString(),
          userId,
          action: `${config.method} ${config.path}`,
          type: 'gamma_api_request',
        }));
        return config;
      },
    },
  });
}
typescript
import { GammaClient } from '@gamma/sdk';

function createAuditedClient(userId: string) {
  return new GammaClient({
    apiKey: process.env.GAMMA_API_KEY,
    interceptors: {
      request: (config) => {
        console.log(JSON.stringify({
          timestamp: new Date().toISOString(),
          userId,
          action: `${config.method} ${config.path}`,
          type: 'gamma_api_request',
        }));
        return config;
      },
    },
  });
}

Security Checklist

安全检查清单

  • API keys stored in environment variables
  • .env files in .gitignore
  • No keys in source code or logs
  • Key rotation procedure documented
  • Minimal permission scopes used
  • Audit logging enabled
  • Webhook signatures verified
  • HTTPS enforced for all calls
  • API密钥存储在环境变量中
  • .env文件已添加到.gitignore
  • 源代码或日志中无密钥
  • 已记录密钥轮换流程
  • 使用最小权限范围
  • 已启用审计日志
  • 已验证Webhook签名
  • 所有调用强制使用HTTPS

Error Handling

错误处理

Security IssueDetectionRemediation
Exposed keyGitHub scanningRotate immediately
Key in logsLog auditFilter sensitive data
Unauthorized accessAudit logsRevoke and investigate
Weak permissionsAccess reviewApply least privilege
安全问题检测方式修复措施
密钥泄露GitHub扫描立即轮换密钥
密钥出现在日志中日志审计过滤敏感数据
未授权访问审计日志吊销权限并调查
权限过大权限审查应用最小权限原则

Resources

参考资源

Next Steps

下一步

Proceed to
gamma-prod-checklist
for production readiness.
请继续查看
gamma-prod-checklist
以确保生产环境就绪。