feat: let administrators view and copy encrypted integration credentials
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/credentialvault"
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
||||
core "git.yuntuo.hk/k2safe/orbit/model"
|
||||
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
||||
@@ -67,7 +68,7 @@ type CredentialChangeInput struct {
|
||||
}
|
||||
|
||||
// CredentialOperation 是可安全重放的私有操作文件内容。
|
||||
// 令牌只存在于 ROTATE 文件中;服务端只保存其摘要和操作回执。
|
||||
// ROTATE 文件包含新令牌;服务端保存摘要、可选密文和不含秘密的操作回执。
|
||||
type CredentialOperation struct {
|
||||
// Version 操作文件格式版本,升级时不得静默改变语义。
|
||||
Version int `json:"version"`
|
||||
@@ -225,12 +226,16 @@ func ValidateCredentialOperation(op CredentialOperation) error {
|
||||
// ApplyCredentialOperation applies one frozen operation or returns its original
|
||||
// receipt. No callback or file I/O occurs inside the transaction. A commit error
|
||||
// is intentionally returned unchanged; replaying the same operation reconciles it.
|
||||
func ApplyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOperation) (CredentialChangeReceipt, error) {
|
||||
return applyCredentialOperation(ctx, db, op, nil)
|
||||
func ApplyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOperation, vault ...*credentialvault.Keyring) (CredentialChangeReceipt, error) {
|
||||
return applyCredentialOperation(ctx, db, op, nil, vault...)
|
||||
}
|
||||
|
||||
// applyCredentialOperation 允许控制台在同一事务先核验管理员,并使用真实人类审计主体。
|
||||
func applyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOperation, authorize func(*sql.Tx) (string, error)) (CredentialChangeReceipt, error) {
|
||||
func applyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOperation, authorize func(*sql.Tx) (string, error), vault ...*credentialvault.Keyring) (CredentialChangeReceipt, error) {
|
||||
var ring *credentialvault.Keyring
|
||||
if len(vault) > 0 {
|
||||
ring = vault[0]
|
||||
}
|
||||
var out CredentialChangeReceipt
|
||||
if err := ValidateCredentialOperation(op); err != nil {
|
||||
return out, err
|
||||
@@ -320,9 +325,14 @@ func applyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOper
|
||||
out.PreviousValidUntil = timePtr(until)
|
||||
}
|
||||
}
|
||||
keyID, ciphertext, err := ring.Seal(op.NamespaceID, op.CredentialID, op.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 未配置保管密钥的旧 CLI 轮换也必须清除旧密文,不能回看过时代次。
|
||||
if _, err := tx.ExecContext(ctx, `UPDATE orbit_credentials
|
||||
SET secret_digest=?,expires_at=?,previous_secret_digest=?,previous_valid_until=?,revision=revision+1,updated_at=?
|
||||
WHERE namespace_id=? AND id=? AND revision=?`, parsed.Digest, op.ExpiresAt, previousDigest, out.PreviousValidUntil, now, op.NamespaceID, op.CredentialID, revision); err != nil {
|
||||
SET secret_digest=?,expires_at=?,previous_secret_digest=?,previous_valid_until=?,secret_key_id=?,secret_ciphertext=?,revision=revision+1,updated_at=?
|
||||
WHERE namespace_id=? AND id=? AND revision=?`, parsed.Digest, op.ExpiresAt, previousDigest, out.PreviousValidUntil, keyID, ciphertext, now, op.NamespaceID, op.CredentialID, revision); err != nil {
|
||||
return err
|
||||
}
|
||||
out.ExpiresAt = op.ExpiresAt
|
||||
@@ -341,7 +351,7 @@ func applyCredentialOperation(ctx context.Context, db *sql.DB, op CredentialOper
|
||||
}
|
||||
out.PreviousValidUntil = nil
|
||||
case credentialRevokeAction:
|
||||
if _, err := tx.ExecContext(ctx, `UPDATE orbit_credentials SET revoked_at=?,previous_secret_digest=NULL,previous_valid_until=NULL,revision=revision+1,updated_at=? WHERE namespace_id=? AND id=? AND revision=?`, now, now, op.NamespaceID, op.CredentialID, revision); err != nil {
|
||||
if _, err := tx.ExecContext(ctx, `UPDATE orbit_credentials SET revoked_at=?,previous_secret_digest=NULL,previous_valid_until=NULL,secret_key_id=NULL,secret_ciphertext=NULL,revision=revision+1,updated_at=? WHERE namespace_id=? AND id=? AND revision=?`, now, now, op.NamespaceID, op.CredentialID, revision); err != nil {
|
||||
return err
|
||||
}
|
||||
out.RevokedAt = timePtr(now)
|
||||
|
||||
Reference in New Issue
Block a user