Roles
A role is an assumable identity — a principal you can switch into by calling Authz.AssumeRole, the way AWS IAM roles work. Roles let one principal act on behalf of another with a time-bounded session, without sharing long-lived credentials. They're the right primitive for cross-workspace access, scoped delegation, and tightly-audited "I need to do one risky thing" workflows. The Go SDK exposes the role methods on client.IAM. For the HTTP surface see API → Roles; for the assume-role flow see Concepts → Authorization.
Field on the Client
client.IAM — the role methods sit alongside the user methods. To assume a role at runtime see client.Authz.AssumeRole(...) on the Authz page.
Methods
ListRoles
Signature. func (r *IamResource) ListRoles(ctx context.Context, auth RequestAuth) ([]IamRole, error)
Lists every role in the workspace. Returns the trust policy inline — handy for an admin UI that shows "who can assume this".
roles, _ := client.IAM.ListRoles(ctx, huudis.RequestAuth{})
for _, r := range roles {
fmt.Println(r.ID, r.Name, r.Description)
}
GetRole
Signature. func (r *IamResource) GetRole(ctx context.Context, id string, auth RequestAuth) (*IamRole, error)
Fetches one role.
role, _ := client.IAM.GetRole(ctx, "role_01HX...", huudis.RequestAuth{})
b, _ := json.MarshalIndent(role.TrustPolicy, "", " ")
fmt.Println(string(b))
CreateRole
Signature. func (r *IamResource) CreateRole(ctx context.Context, in CreateRoleInput, auth RequestAuth) (*IamRole, error)
Creates a role. TrustPolicy is required — it spells out which principals can assume this role. The document follows the same JSON shape as access policies with one rule:
Effect:AllowPrincipal: the ARN(s) allowed to assumeAction:iam:AssumeRole
role, err := client.IAM.CreateRole(ctx, huudis.CreateRoleInput{
Name: "BillingReader",
Description: "Cross-team read access to billing data",
TrustPolicy: map[string]any{
"Version": "2026-01-01",
"Statement": []map[string]any{{
"Effect": "Allow",
"Principal": map[string]any{"AWS": fmt.Sprintf("arn:huudis:iam::%s:group/Finance", accountID)},
"Action": "iam:AssumeRole",
}},
},
}, huudis.RequestAuth{})
if err != nil {
return err
}
log.Println(role.ID)
After creation, attach an access policy to the role (client.IAM.AttachPolicy(...)) — the trust policy says who can be the role; the access policy says what the role can do.
DeleteRole
Signature. func (r *IamResource) DeleteRole(ctx context.Context, id string, auth RequestAuth) error
Removes the role. Active assumed-role sessions issued from it stay alive until they expire (max 12 hours; usually much less); refresh is blocked.
_ = client.IAM.DeleteRole(ctx, "role_01HX...", huudis.RequestAuth{})
Types
type IamRole struct {
ID string `json:"id"` // "role_..."
AccountID string `json:"accountId"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
TrustPolicy map[string]any `json:"trustPolicy,omitempty"`
CreatedAt string `json:"createdAt"` // ISO-8601
}
The trust policy document follows the Huudis policy language — same grammar as access policies, restricted action set. See API → Roles for the full spec.
Common patterns
Cross-workspace delegation
Workspace A grants workspace B's support team read access to a slice of data. A creates a role whose trust policy names B's support group; B's users AssumeRole into A.
// In workspace A:
role, _ := client.IAM.CreateRole(ctx, huudis.CreateRoleInput{
Name: "SupportReader",
TrustPolicy: map[string]any{
"Version": "2026-01-01",
"Statement": []map[string]any{{
"Effect": "Allow",
"Principal": map[string]any{"AWS": "arn:huudis:iam::acc_B_id:group/Support"},
"Action": "iam:AssumeRole",
"Condition": map[string]any{
"StringEquals": map[string]any{"aws:MultiFactorAuthPresent": "true"},
},
}},
},
}, huudis.RequestAuth{})
_, _ = client.IAM.AttachPolicy(ctx, huudis.AttachPolicyInput{
PolicyID: readonlyPolicyID,
PrincipalArn: fmt.Sprintf("arn:huudis:iam::%s:role/%s", accountIDA, role.Name),
}, huudis.RequestAuth{})
// In workspace B (later):
session, _ := client.Authz.AssumeRole(ctx, huudis.AssumeRoleInput{
RoleArn: "arn:huudis:iam::acc_A_id:role/SupportReader",
SessionName: "ticket-" + ticketID,
DurationSeconds: 3600,
}, huudis.RequestAuth{})
_ = session
Time-bounded escalation
A user is normally a viewer but needs admin briefly. Build a role with broader access and a trust policy gated by MFA + a self-approval workflow:
_, _ = client.IAM.CreateRole(ctx, huudis.CreateRoleInput{
Name: "BreakglassAdmin",
TrustPolicy: map[string]any{
"Version": "2026-01-01",
"Statement": []map[string]any{{
"Effect": "Allow",
"Principal": map[string]any{"AWS": fmt.Sprintf("arn:huudis:iam::%s:group/On-call", accountID)},
"Action": "iam:AssumeRole",
"Condition": map[string]any{
"Bool": map[string]any{"aws:MultiFactorAuthPresent": "true"},
"DateLessThan": map[string]any{"aws:CurrentTime": futureIso},
},
}},
},
}, huudis.RequestAuth{})
Pair with an audit watch on huudis.iam.role_assumed.v1 events so the security team sees every escalation.
Audit unused roles
A role you can't recall the purpose of is one you can probably delete. Cross-reference with the audit log:
func unusedRoles(ctx context.Context, c *huudis.Client, maxDays int) ([]huudis.IamRole, error) {
roles, err := c.IAM.ListRoles(ctx, huudis.RequestAuth{})
if err != nil {
return nil, err
}
since := time.Now().Add(-time.Duration(maxDays) * 24 * time.Hour).Format(time.RFC3339)
audit, err := c.Account.Audit(ctx, huudis.AuditParams{
EventType: "huudis.iam.role_assumed.v1",
Since: since,
Limit: 1000,
}, huudis.RequestAuth{})
if err != nil {
return nil, err
}
used := map[string]bool{}
for _, e := range audit {
used[e.Resource] = true
}
var stale []huudis.IamRole
for _, r := range roles {
arn := fmt.Sprintf("arn:huudis:iam::%s:role/%s", r.AccountID, r.Name)
if !used[arn] {
stale = append(stale, r)
}
}
return stale, nil
}
Errors
Code |
Status |
Cause |
|---|---|---|
validation_error |
400 | Bad trust policy JSON, missing Action: "iam:AssumeRole", name too long. |
not_found |
404 | Role ID doesn't exist or lives in another workspace. |
conflict |
409 | Name already used in this workspace. |
forbidden |
403 | Caller isn't an admin/owner. |
Next
- Policies — the access policies you attach to roles.
- Authz — the
AssumeRole+Checkruntime surface. - API → Roles — HTTP-level reference.