概述
本章节主要介绍凭证管理中的访问凭证相关功能以及使用凭证访问沙箱实例。访问凭证主要包含3种类型,即:API Key、Basic Auth和JWT。如果沙箱模板中配置了访问凭证,那么在访问沙箱实例时,就需要配置对应的请求头。
访问凭证管理
查看访问凭证
操作步骤
登录智能体引擎控制台。
在左侧导航选择凭证管理菜单下,查看访问凭证列表。
创建访问凭证
操作步骤
登录智能体引擎控制台。
左侧导航凭证管理菜单下,点击创建凭证,填写访问凭证配置内容,然后点击确定。
API Key类型访问凭证
API Key类型访问凭证创建参数说明如下:
| 参数名称 | 是否必填 | 参数说明 |
|---|---|---|
| 凭证名称 | 是 | 访问凭证名称同租户下唯一。 凭证名称规则:必须以字母开头,只能包含字母、数字、中划线和下划线,长度1-32个字符。 |
| 描述 | 否 | 访问凭证描述。 |
| 认证类型 | 是 | 认证类型支持3种,即:API Key、Basic Auth和JWT |
| 设置为沙箱调试默认凭证 | 是 | 沙箱调试时需要使用API Key类型的凭证。使用沙箱调试功能必须确保有默认的API Key类型访问凭证。 |
注意:API Key的值只在创建成功后展示,需要妥善保管,后续无法查看。
Basic Auth类型访问凭证
Basic Auth类型访问凭证创建参数说明如下:
| 参数名称 | 是否必填 | 参数说明 |
|---|---|---|
| 凭证名称 | 是 | 访问凭证名称同租户下唯一。 凭证名称规则:必须以字母开头,只能包含字母、数字、中划线和下划线,长度1-32个字符。 |
| 描述 | 否 | 访问凭证描述。 |
| 认证类型 | 是 | 认证类型支持3种,即:API Key、Basic Auth和JWT |
| 用户名 | 是 | 用户名规则:必须以字母开头,只能包含字母、数字、下划线和中划线,长度1-32个字符。 |
| 密码 | 是 | 密码长度8-32个字符。 |
JWT类型访问凭证
JWT类型访问凭证创建参数说明如下:
| 参数名称 | 是否必填 | 参数说明 |
|---|---|---|
| 凭证名称 | 是 | 访问凭证名称同租户下唯一。 凭证名称规则:必须以字母开头,只能包含字母、数字、中划线和下划线,长度1-32个字符。 |
| 描述 | 否 | 访问凭证描述。 |
| 认证类型 | 是 | 认证类型支持3种,即:API Key、Basic Auth和JWT |
| JWKS配置 | 是 | JWKS目前只支持RS256算法 |
生成JWKS配置以及JWT,可以参考如下golang程序
func TestRsaJwksAndJWT(t *testing.T) {
// 定义要测试的 RSA 签名算法列表
algs := []string{
jwt.SigningMethodRS256.Name,
}
// 存储每种算法对应的私钥,用于后续 JWT 签名
privateKeys := make(map[string]*rsa.PrivateKey)
// 构建 JWKS
keySet := jwk.NewSet()
// 为每种算法生成独立的 RSA 密钥对,并添加到 JWKS
for _, alg := range algs {
// 生成 RSA 密钥对
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("生成 RSA 私钥失败 (alg=%s): %v", alg, err)
}
privateKeys[alg] = privateKey
// 从私钥获取公钥
publicKey := &privateKey.PublicKey
// 构建 JWK
jwkKey, err := jwk.FromRaw(publicKey)
if err != nil {
t.Fatalf("构建 JWK 失败 (alg=%s): %v", alg, err)
}
// 设置必要属性
if err := jwkKey.Set(jwk.KeyUsageKey, "sig"); err != nil {
t.Fatalf("设置 use 属性失败 (alg=%s): %v", alg, err)
}
if err := jwkKey.Set(jwk.AlgorithmKey, alg); err != nil {
t.Fatalf("设置 alg 属性失败 (alg=%s): %v", alg, err)
}
// 设置唯一的 kid(基于算法名称)
kid := fmt.Sprintf("%s-key", alg)
if err := jwkKey.Set(jwk.KeyIDKey, kid); err != nil {
t.Fatalf("设置 kid 属性失败 (alg=%s): %v", alg, err)
}
// 添加到 JWKS
keySet.AddKey(jwkKey)
// 打印 PEM 格式的私钥和公钥
fmt.Printf("=== RSA 密钥对 (alg=%s) ===\n", alg)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
fmt.Println("私钥 (PEM):")
fmt.Println(string(privateKeyPEM))
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
t.Fatalf("序列化公钥失败 (alg=%s): %v", alg, err)
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
})
fmt.Println("公钥 (PEM):")
fmt.Println(string(publicKeyPEM))
fmt.Println()
}
// 序列化 JWKS 为 JSON
jwksJSON, err := json.MarshalIndent(keySet, "", " ")
if err != nil {
t.Fatalf("序列化 JWKS 失败: %v", err)
}
fmt.Println("=== JWKS (包含所有算法的公钥) ===")
fmt.Println(string(jwksJSON))
// 标准载荷(RegisteredClaims)
now := time.Now()
claims := &jwt.RegisteredClaims{
Issuer: "example-issuer",
Subject: "1234567890",
Audience: []string{"example-audience"},
ExpiresAt: jwt.NewNumericDate(now.Add(time.Hour * 24 * 30)),
NotBefore: jwt.NewNumericDate(now),
IssuedAt: jwt.NewNumericDate(now),
ID: "unique-jwt-id-" + now.Format("20060102150405"),
}
// 遍历每种算法,生成并验证 JWT
for _, alg := range algs {
t.Run(alg, func(t *testing.T) {
privateKey := privateKeys[alg]
// 创建 JWT 令牌
token := jwt.NewWithClaims(jwt.GetSigningMethod(alg), claims)
// 签名
signedToken, err := token.SignedString(privateKey)
if err != nil {
t.Fatalf("签署 JWT 失败 (alg=%s): %v", alg, err)
}
fmt.Printf("=== JWT (alg=%s) ===\n%s\n\n", alg, signedToken)
// 验证 JWT:从 JWKS 中根据 kid 匹配公钥(kid 格式为 "算法-key")
parsedSet, err := jwk.Parse(jwksJSON)
if err != nil {
t.Fatalf("解析 JWKS 失败: %v", err)
}
// 根据算法构造期望的 kid
expectedKid := fmt.Sprintf("%s-key", alg)
// 通过 LookupKeyID 直接获取对应的 JWK
targetKey, ok := parsedSet.LookupKeyID(expectedKid)
if !ok {
t.Fatalf("未找到 kid 为 %s 的公钥", expectedKid)
}
var pubKeyRaw interface{}
if err := targetKey.Raw(&pubKeyRaw); err != nil {
t.Fatalf("获取原始公钥失败: %v", err)
}
// 解析并验证签名
parsedToken, err := jwt.ParseWithClaims(signedToken, &jwt.RegisteredClaims{}, func(token *jwt.Token) (interface{}, error) {
if token.Method.Alg() != alg {
return nil, jwt.ErrSignatureInvalid
}
return pubKeyRaw, nil
}, jwt.WithLeeway(5*time.Second))
if err != nil {
t.Fatalf("验证 JWT 失败: %v", err)
}
if !parsedToken.Valid {
t.Fatal("JWT 无效")
}
// 验证载荷
gotClaims, ok := parsedToken.Claims.(*jwt.RegisteredClaims)
if !ok {
t.Fatal("Claims 类型不正确")
}
if gotClaims.Subject != claims.Subject {
t.Errorf("subject 不匹配: got %v, want %v", gotClaims.Subject, claims.Subject)
}
if gotClaims.Issuer != claims.Issuer {
t.Errorf("issuer 不匹配: got %v, want %v", gotClaims.Issuer, claims.Issuer)
}
t.Logf("算法 %s 验证通过", alg)
})
}
}编辑访问凭证
操作步骤
登录智能体引擎控制台。
左侧导航到凭证管理菜单下,找到需要编辑的访问凭证,在操作列点击编辑,根据不同类型的访问凭证进行修改,点击确定。 和创建访问凭证基本相同,除了凭证名称不能修改,这里就不再赘述了。
删除访问凭证
操作步骤
登录智能体引擎控制台。
左侧导航到凭证管理菜单下,找到需要删除的身份凭证,在操作列点击删除,确认无误后,点击确定。 如果访问凭证关联了智能体或者模板资源,需要先解绑才能删除。
访问沙箱实例
前置条件
登录智能体引擎控制台。
已分别创建好配置有3种访问凭证类型的沙箱模板,并且已创建对应的沙箱实例。
使用API Key类型访问凭证
沙箱模板配置了API Key类型的访问凭证,在使用E2B SDK访问沙箱时,需要在headers中增加请求头X-AGE-Access-API-Key并且值正确才能访问沙箱,如果缺失该请求头或者请求头的值不正确,均无法访问沙箱。
下面给出一个连接沙箱并且写入文件的示例。具体参数值根据实际情况填入即可。
# 连接沙箱
sandbox = Sandbox.connect(
sandbox_id= "xxx",
headers={"X-AGE-Access-API-Key": "age_xxx"})
# 写入文件
print("开始测试写入文件")
write_info = sandbox.files.write("/home/user/test.txt", "Hello World")
print(f"写入文件: {write_info.path}")使用Basic Auth类型访问凭证
沙箱模板配置了Basic Auth类型的访问凭证,在使用E2B SDK访问沙箱时,需要在headers中增加请求头X-AGE-Access-Authorization并且值为Basic <base64(username:password),如果缺失该请求头或者请求头的值不正确,均无法访问沙箱。
示例同使用API Key类型访问凭证,只是请求头不同,这里就不再赘述了。
使用JWT类型访问凭证
沙箱模板配置了JWT类型的访问凭证,在使用E2B SDK访问沙箱时,需要在headers中增加请求头X-AGE-Access-Authorization并且值为Bearer ,如果缺失该请求头或者请求头的值不正确,均无法访问沙箱。
示例同使用API Key类型访问凭证,只是请求头不同,这里就不再赘述了。