feat: let administrators view and copy encrypted integration credentials

This commit is contained in:
2026-09-27 13:48:26 +08:00
parent 5555a7b342
commit d54bdd9847
38 changed files with 905 additions and 71 deletions

View File

@@ -9,6 +9,7 @@ import (
"time"
"git.yuntuo.hk/k2safe/orbit/internal/consoleauth"
"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"
@@ -21,10 +22,15 @@ import (
type ConsoleApplicationStore struct {
db *sql.DB
username string
vault *credentialvault.Keyring
}
func NewConsoleApplicationStore(db *sql.DB, username string) *ConsoleApplicationStore {
return &ConsoleApplicationStore{db: db, username: username}
func NewConsoleApplicationStore(db *sql.DB, username string, vault ...*credentialvault.Keyring) *ConsoleApplicationStore {
s := &ConsoleApplicationStore{db: db, username: username}
if len(vault) > 0 {
s.vault = vault[0]
}
return s
}
var _ consoleauth.Applications = (*ConsoleApplicationStore)(nil)
@@ -32,7 +38,7 @@ var _ consoleauth.Applications = (*ConsoleApplicationStore)(nil)
// admin 在实际读写事务中锁定人类账号及会话;普通 SDK Token 无对应会话,无法通过。
// 不锁业务凭据,轮换当前账号所绑定的 SDK 凭据也不会产生共享锁升级。
func (s *ConsoleApplicationStore) admin(ctx context.Context, tx *sql.Tx, token auth.Token) (string, error) {
if s.username == "" {
if s.username == "" || token.NamespaceID.Validate() != nil || token.CredentialID.Validate() != nil {
return "", fault.Forbidden
}
var user core.ID
@@ -117,7 +123,8 @@ func (s *ConsoleApplicationStore) GetApplication(ctx context.Context, token auth
if err != nil {
return err
}
rows, err = tx.QueryContext(ctx, `SELECT id,name,revision,expires_at,revoked_at,previous_valid_until,permissions FROM orbit_credentials WHERE namespace_id=? ORDER BY id LIMIT 101`, namespace)
out.TokenVaultEnabled = s.vault != nil
rows, err = tx.QueryContext(ctx, `SELECT id,name,revision,expires_at,revoked_at,previous_valid_until,permissions,secret_ciphertext IS NOT NULL FROM orbit_credentials WHERE namespace_id=? ORDER BY id LIMIT 101`, namespace)
if err != nil {
return err
}
@@ -126,7 +133,7 @@ func (s *ConsoleApplicationStore) GetApplication(ctx context.Context, token auth
var c consoleauth.AccessCredential
var expires, revoked, previous sql.NullTime
var raw []byte
if err := rows.Scan(&c.ID, &c.Name, &c.Revision, &expires, &revoked, &previous, &raw); err != nil {
if err := rows.Scan(&c.ID, &c.Name, &c.Revision, &expires, &revoked, &previous, &raw, &c.TokenStored); err != nil {
return err
}
if err := json.Unmarshal(raw, &c.Permissions); err != nil {
@@ -299,7 +306,7 @@ func (s *ConsoleApplicationStore) ApplyApplication(ctx context.Context, token au
return "", fault.Invalid("application identity mismatch")
}
return actor, nil
})
}, s.vault)
return consoleauth.ApplicationReceipt{OperationID: op.OperationID, ApplicationID: op.ApplicationID, NamespaceID: op.NamespaceID, CredentialID: op.CredentialID, Revision: receipt.Revision, Deduplicated: receipt.Deduplicated}, err
}
parsed, err := auth.Parse(op.Token)
@@ -352,6 +359,10 @@ func (s *ConsoleApplicationStore) ApplyApplication(ctx context.Context, token au
if op.ExpiresAt != nil && (!op.ExpiresAt.After(now) || op.ExpiresAt.After(now.Add(365*24*time.Hour))) {
return fault.Invalid("expired or excessive credential lifetime")
}
keyID, ciphertext, err := s.vault.Seal(op.NamespaceID, op.CredentialID, op.Token)
if err != nil {
return err
}
statements := []struct {
query string
args []any
@@ -360,7 +371,7 @@ func (s *ConsoleApplicationStore) ApplyApplication(ctx context.Context, token au
{`INSERT INTO orbit_application_resources(application_id) VALUES (?)`, []any{op.ApplicationID}},
{`INSERT INTO orbit_namespaces(id,application_id,name,environment) VALUES (?,?,?,?)`, []any{op.NamespaceID, op.ApplicationID, op.Input.Namespace, op.Input.Environment}},
{`INSERT INTO pulse_queues(namespace_id,id,name,max_concurrency,rate_per_second,policy) VALUES (?,?,?,4,10,'{}')`, []any{op.NamespaceID, op.QueueID, op.Input.Queue}},
{`INSERT INTO orbit_credentials(namespace_id,id,name,secret_digest,permissions,expires_at) VALUES (?,?,'console-issued',?,?,?)`, []any{op.NamespaceID, op.CredentialID, parsed.Digest, string(raw), op.ExpiresAt}},
{`INSERT INTO orbit_credentials(namespace_id,id,name,secret_digest,permissions,expires_at,secret_key_id,secret_ciphertext) VALUES (?,?,'console-issued',?,?,?,?,?)`, []any{op.NamespaceID, op.CredentialID, parsed.Digest, string(raw), op.ExpiresAt, keyID, ciphertext}},
}
for _, st := range statements {
if _, err := tx.ExecContext(ctx, st.query, st.args...); err != nil {