使用AWS Go SDK解密Lambda环境变量时遇InvalidCiphertextException错误
解决AWS Lambda环境变量KMS解密的InvalidCiphertextException问题
问题背景
尝试使用AWS Go SDK解密经KMS加密的Lambda环境变量,加密和解密使用同一KMS密钥,已为Lambda附加权限策略,但调用Decrypt接口时返回InvalidCiphertextException错误。
附加的权限策略:
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "kms:*", "Resource": "arn:aws:kms:us-west-2:602487775829:key/f91a9f1a-9b53-4544-xxxxxxxx", "Condition": { "StringEquals": { "kms:EncryptionContext:LambdaFunctionName": "eLead" } } } }
原解密代码片段:
import ( "os" "context" "encoding/base64" "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go-v2/config" ) var API_key = os.Getenv("API_key") var API_Secret = os.Getenv("API_Secret") func Handler(ctx context.Context) error { cfg, err := config.LoadDefaultConfig(context.TODO(),config.WithRegion("us-west-2")) API_key_blob, err := base64.StdEncoding.DecodeString(API_key) API_Secret_blob, err := base64.StdEncoding.DecodeString(API_Secret) keyID := "arn:aws:kms:us-west-2:602487775829:key/f91a9f1a-9b53-4544-a05b-xxxxxx" API_key_result, err := kmsClient.Decrypt(context.TODO(), &kms.DecryptInput{ CiphertextBlob: API_key_blob, KeyId:aws.String(keyID), }) API_Secret_result, err := kmsClient.Decrypt(context.TODO(),&kms.DecryptInput{ CiphertextBlob: API_Secret_blob, KeyId:aws.String(keyID), }) if err != nil { fmt.Println("Got error decrypting data: ", err) return err } func main() { lambda.Start(Handler) }
错误信息:
Got error decrypting data: operation error KMS: Decrypt, https response error StatusCode: 400, RequestID: 629a64b2-ce53-46ad-88fb-1f6ac684919e, InvalidCiphertextException:
排查与解决步骤
1. 修复KMS客户端初始化缺失问题
原代码中kmsClient未初始化,这是直接导致调用失败的基础问题。加载AWS配置后,必须创建KMS客户端实例:
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2")) if err != nil { fmt.Println("Failed to load config: ", err) return err } kmsClient := kms.NewFromConfig(cfg) // 新增该行初始化客户端
2. 传入匹配的加密上下文
Lambda加密环境变量时会自动添加包含LambdaFunctionName的加密上下文,解密时必须传入完全一致的上下文,否则会触发权限策略的条件检查失败,同时导致解密报错。修改DecryptInput参数:
API_key_result, err := kmsClient.Decrypt(context.TODO(), &kms.DecryptInput{ CiphertextBlob: API_key_blob, KeyId: aws.String(keyID), EncryptionContext: map[string]string{ "LambdaFunctionName": "eLead", // 和策略中的条件值保持一致 }, })
3. 验证环境变量完整性
- 确认Lambda控制台中加密的环境变量值未被篡改、截断,确保
os.Getenv获取到的是完整的Base64加密字符串。 - 可临时在代码中打印环境变量值(注意不要泄露敏感信息),验证是否与控制台显示一致。
4. 确认KMS密钥ARN完全匹配
检查策略中的密钥ARN与代码中使用的密钥ID是否为同一密钥,避免因密钥不匹配导致解密失败。
5. 完善错误处理逻辑
原代码中连续调用解码、解密操作时,仅在最后统一处理错误,会导致前面的错误被覆盖。建议每一步操作单独处理错误,方便定位问题:
API_key_blob, err := base64.StdEncoding.DecodeString(API_key) if err != nil { fmt.Println("Failed to decode API_key: ", err) return err } API_Secret_blob, err := base64.StdEncoding.DecodeString(API_Secret) if err != nil { fmt.Println("Failed to decode API_Secret: ", err) return err }
完整修正后的代码示例
import ( "context" "encoding/base64" "fmt" "os" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/kms" "github.com/aws/aws-lambda-go/lambda" ) var API_key = os.Getenv("API_key") var API_Secret = os.Getenv("API_Secret") func Handler(ctx context.Context) error { // 加载AWS配置 cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2")) if err != nil { fmt.Println("Failed to load AWS config: ", err) return err } // 初始化KMS客户端 kmsClient := kms.NewFromConfig(cfg) // 解码Base64加密字符串 API_key_blob, err := base64.StdEncoding.DecodeString(API_key) if err != nil { fmt.Println("Failed to decode API_key: ", err) return err } API_Secret_blob, err := base64.StdEncoding.DecodeString(API_Secret) if err != nil { fmt.Println("Failed to decode API_Secret: ", err) return err } keyID := "arn:aws:kms:us-west-2:602487775829:key/f91a9f1a-9b53-4544-a05b-xxxxxx" // 解密API_key API_key_result, err := kmsClient.Decrypt(context.TODO(), &kms.DecryptInput{ CiphertextBlob: API_key_blob, KeyId: aws.String(keyID), EncryptionContext: map[string]string{"LambdaFunctionName": "eLead"}, }) if err != nil { fmt.Println("Got error decrypting API_key: ", err) return err } // 解密API_Secret API_Secret_result, err := kmsClient.Decrypt(context.TODO(), &kms.DecryptInput{ CiphertextBlob: API_Secret_blob, KeyId: aws.String(keyID), EncryptionContext: map[string]string{"LambdaFunctionName": "eLead"}, }) if err != nil { fmt.Println("Got error decrypting API_Secret: ", err) return err } // 使用解密后的值(生产环境请勿打印敏感信息) fmt.Println("Decrypted API_key: ", string(API_key_result.Plaintext)) fmt.Println("Decrypted API_Secret: ", string(API_Secret_result.Plaintext)) return nil } func main() { lambda.Start(Handler) }
内容的提问来源于stack exchange,提问作者celianiu
相关产品推荐
相关产品推荐

