feat(apptoken): Add scope type retrieval for app token id

Useful for determining which app token subtype table to operate on (global vs org vs project)
pull/6420/merge^2
dkanney 4 weeks ago
parent 99d1ba97bb
commit c1541159c0

@ -402,4 +402,9 @@ left join iam_scope_project
from pg_class
where oid in ('app_token_global'::regclass, 'app_token_org'::regclass, 'app_token_project'::regclass)
`
scopeIdFromAppTokenIdQuery = `
select scope_id
from app_token
where public_id = @public_id;`
)

@ -16,8 +16,10 @@ import (
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/perms"
"github.com/hashicorp/boundary/internal/types/scope"
)
// Repository is the apptoken database repository
@ -623,3 +625,88 @@ func (r *Repository) estimatedCount(ctx context.Context) (int, error) {
}
return count, nil
}
// getAppTokenScopeType returns the [scope.Type] of an App Token by reading it from the base type app_token table.
// Use this to get scope ID to determine which of the app token subtype tables to operate on.
func getAppTokenScopeType(ctx context.Context, reader db.Reader, id string) (scope.Type, error) {
const op = "apptoken.getAppTokenScopeType"
if id == "" {
return scope.Unknown, errors.New(ctx, errors.InvalidParameter, op, "missing app token id")
}
if reader == nil {
return scope.Unknown, errors.New(ctx, errors.InvalidParameter, op, "missing db.Reader")
}
rows, err := reader.Query(ctx, scopeIdFromAppTokenIdQuery, []any{sql.Named("public_id", id)})
if err != nil {
return scope.Unknown, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed to lookup app token scope for id: %s", id)))
}
defer rows.Close()
var scopeIds []string
for rows.Next() {
if err := reader.ScanRows(ctx, rows, &scopeIds); err != nil {
return scope.Unknown, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed scan results from querying app token scope for id: %s", id)))
}
}
if err := rows.Err(); err != nil {
return scope.Unknown, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unexpected error scanning results from querying app token scope for id: %s", id)))
}
if len(scopeIds) == 0 {
return scope.Unknown, errors.New(ctx, errors.RecordNotFound, op, fmt.Sprintf("app token %s not found", id))
}
if len(scopeIds) > 1 {
return scope.Unknown, errors.New(ctx, errors.MultipleRecords, op, fmt.Sprintf("expected 1 row but got: %d", len(scopeIds)))
}
scopeId := scopeIds[0]
switch {
case strings.HasPrefix(scopeId, globals.GlobalPrefix):
return scope.Global, nil
case strings.HasPrefix(scopeId, globals.OrgPrefix):
return scope.Org, nil
case strings.HasPrefix(scopeId, globals.ProjectPrefix):
return scope.Project, nil
default:
return scope.Unknown, fmt.Errorf("unknown scope type for app token %s", id)
}
}
// getAppTokenScope returns the scope of the app token
func getAppTokenScope(ctx context.Context, r db.Reader, id string) (*iam.Scope, error) {
const op = "apptoken.getAppTokenScope"
if id == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing app token id")
}
if r == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing db.Reader")
}
rows, err := r.Query(ctx, scopeIdFromAppTokenIdQuery, []any{sql.Named("public_id", id)})
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed to lookup app token scope for :%s", id)))
}
defer rows.Close()
var scopeIds []string
for rows.Next() {
if err := r.ScanRows(ctx, rows, &scopeIds); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed scan results from querying app token scope for :%s", id)))
}
}
if err := rows.Err(); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unexpected error scanning results from querying app token scope for :%s", id)))
}
if len(scopeIds) == 0 {
return nil, errors.New(ctx, errors.RecordNotFound, op, fmt.Sprintf("app token %s not found", id))
}
if len(scopeIds) > 1 {
return nil, errors.New(ctx, errors.MultipleRecords, op, fmt.Sprintf("expected 1 row but got: %d", len(scopeIds)))
}
scp := iam.AllocScope()
scp.PublicId = scopeIds[0]
err = r.LookupByPublicId(ctx, &scp)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("failed to lookup app token scope"))
}
return &scp, nil
}

@ -69,14 +69,14 @@ func (r *Repository) GrantsForToken(ctx context.Context, tokenId string, res []r
opts := getOpts(opt...)
// get AppToken to get scope
appToken, err := r.getAppTokenById(ctx, tokenId)
scope, err := getAppTokenScope(ctx, r.reader, tokenId)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
scopeId := scope.GetPublicId()
// find the correct query to use
query, err := r.resolveAppTokenQuery(ctx, appToken.ScopeId, res, reqScopeId, opts.withRecursive)
query, err := r.resolveAppTokenQuery(ctx, scopeId, res, reqScopeId, opts.withRecursive)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
@ -135,7 +135,7 @@ func (r *Repository) GrantsForToken(ctx context.Context, tokenId string, res []r
for _, grant := range grants {
resp = append(resp, tempGrantTuple{
AppTokenId: grant.AppTokenId,
AppTokenScopeId: appToken.ScopeId,
AppTokenScopeId: scopeId,
AppTokenParentScopeId: grant.AppTokenParentScopeId,
GrantScopeId: grant.GrantScope,
Grant: strings.Join(grant.CanonicalGrants, ","),

Loading…
Cancel
Save