guidewire-enterprise-rbac
Implement enterprise role-based access control for Guidewire InsuranceSuite including API roles, user permissions, and security policies. Trigger with phrases like "guidewire rbac", "permissions guidewire", "user roles", "api access control", "security permissions". allowed-tools: Read, Write, Edit, Bash(curl:*), Grep version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>
Allowed Tools
No tools specified
Provided by Plugin
guidewire-pack
Claude Code skill pack for Guidewire InsuranceSuite (24 skills)
Installation
This skill is included in the guidewire-pack plugin:
/plugin install guidewire-pack@claude-code-plugins-plus
Click to copy
Instructions
# Guidewire Enterprise RBAC
## Overview
Implement comprehensive role-based access control for Guidewire InsuranceSuite including API roles, user permissions, system roles, and security policies.
## Prerequisites
- Access to Guidewire Cloud Console (GCC)
- Understanding of OAuth2 and JWT
- Knowledge of enterprise security patterns
## RBAC Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Guidewire RBAC Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Guidewire Hub (IdP) β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β β β Users β β Groups β β Applicationsβ β Roles β β β
β β β β β β β β β β β β
β β β β’ Internal β β β’ AD Sync β β β’ Browser β β β’ API Roles β β β
β β β β’ External β β β’ Manual β β β’ Service β β β’ App Roles β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββΌββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββββββββββββββββ βββββββββββββββββββββββββ βββββββββββββββββββββββββ β
β β PolicyCenter β β ClaimCenter β β BillingCenter β β
β β β β β β β β
β β System Roles: β β System Roles: β β System Roles: β β
β β β’ Underwriter β β β’ Claims Adjuster β β β’ Billing Admin β β
β β β’ Policy Admin β β β’ Claims Supervisor β β β’ Payment Handler β β
β β β’ Agent β β β’ SIU Investigator β β β’ Collections Agent β β
β β β β β β β β
β β API Roles: β β API Roles: β β API Roles: β β
β β β’ pc_policy_read β β β’ cc_claim_read β β β’ bc_billing_read β β
β β β’ pc_policy_admin β β β’ cc_claim_admin β β β’ bc_payment_admin β β
β βββββββββββββββββββββββββ βββββββββββββββββββββββββ βββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Instructions
### Step 1: Configure API Roles in GCC
```yaml
# API Role Configuration
# Guidewire Cloud Console > Identity & Access > API Roles
api_roles:
# Read-only roles
- name: pc_policy_read
application: PolicyCenter
description: Read-only access to policies and accounts
permissions:
- endpoint: /account/v1/accounts
operations: [GET]
- endpoint: /account/v1/accounts/{id}
operations: [GET]
- endpoint: /policy/v1/policies
operations: [GET]
- endpoint: /policy/v1/policies/{id}
operations: [GET]
# Admin roles
- name: pc_policy_admin
application: PolicyCenter
description: Full access to policy administration
permissions:
- endpoint: /account/v1/accounts
operations: [GET, POST, PATCH]
- endpoint: /job/v1/submissions
operations: [GET, POST, PATCH]
- endpoint: /job/v1/submissions/{id}/quote
operations: [POST]
- endpoint: /job/v1/submissions/{id}/bind
operations: [POST]
- endpoint: /policy/v1/policies
operations: [GET, POST, PATCH]
# Claims roles
- name: cc_claim_admin
application: ClaimCenter
description: Full access to claims management
permissions:
- endpoint: /claim/v1/claims
operations: [GET, POST, PATCH]
- endpoint: /fnol/v1/fnol
operations: [POST]
- endpoint: /claim/v1/claims/{id}/exposures
operations: [GET, POST, PATCH]
- endpoint: /claim/v1/claims/{id}/payments
operations: [GET, POST]
```
### Step 2: Service Account Configuration
```typescript
// Service account management
interface ServiceAccount {
clientId: string;
name: string;
description: string;
apiRoles: string[];
environments: string[];
}
const serviceAccounts: ServiceAccount[] = [
{
clientId: 'integration-service-prod',
name: 'Integration Service',
description: 'Backend integration service for policy and claims sync',
apiRoles: ['pc_policy_admin', 'cc_claim_read'],
environments: ['production']
},
{
clientId: 'agent-portal-prod',
name: 'Agent Portal',
description: 'Agent-facing portal application',
apiRoles: ['pc_policy_read', 'pc_submission_handler'],
environments: ['production', 'uat']
},
{
clientId: 'reporting-service',
name: 'Reporting Service',
description: 'Read-only access for reporting',
apiRoles: ['pc_policy_read', 'cc_claim_read', 'bc_billing_read'],
environments: ['production']
}
];
// Register service account in GCC
async function registerServiceAccount(account: ServiceAccount): Promise {
const response = await gccClient.post('/api/v1/applications', {
clientId: account.clientId,
name: account.name,
description: account.description,
type: 'service',
apiRoles: account.apiRoles.map(role => ({ name: role }))
});
console.log(`Registered service account: ${account.clientId}`);
}
```
### Step 3: User Role Management in Gosu
```gosu
// User role management
package gw.security.roles
uses gw.api.util.Logger
uses gw.pl.persistence.core.Bundle
class RoleManager {
private static final var LOG = Logger.forCategory("RoleManager")
// Assign role to user
static function assignRole(user : User, roleCode : String) {
var role = Role.get(roleCode)
if (role == null) {
throw new IllegalArgumentException("Role not found: ${roleCode}")
}
if (user.hasRole(role)) {
LOG.info("User ${user.UserName} already has role ${roleCode}")
return
}
gw.transaction.Transaction.runWithNewBundle(\bundle -> {
var u = bundle.add(user)
var userRole = new UserRole(bundle)
userRole.User = u
userRole.Role = role
LOG.info("Assigned role ${roleCode} to user ${user.UserName}")
})
}
// Remove role from user
static function removeRole(user : User, roleCode : String) {
var role = Role.get(roleCode)
if (role == null) {
throw new IllegalArgumentException("Role not found: ${roleCode}")
}
gw.transaction.Transaction.runWithNewBundle(\bundle -> {
var u = bundle.add(user)
var userRole = u.Roles.firstWhere(\ur -> ur.Role == role)
if (userRole != null) {
bundle.delete(userRole)
LOG.info("Removed role ${roleCode} from user ${user.UserName}")
}
})
}
// Check if user has permission
static function hasPermission(user : User, permission : String) : boolean {
return user.Roles.hasMatch(\ur ->
ur.Role.Permissions.hasMatch(\p -> p.Code == permission)
)
}
// Get all permissions for user
static function getUserPermissions(user : User) : Set {
var permissions = new HashSet()
user.Roles.each(\ur -> {
ur.Role.Permissions.each(\p -> {
permissions.add(p.Code)
})
})
return permissions
}
}
```
### Step 4: Custom Permission Checks
```gosu
// Custom permission framework
package gw.security.permissions
uses gw.api.util.Logger
uses gw.api.web.SessionUtil
class PermissionChecker {
private static final var LOG = Logger.forCategory("PermissionChecker")
// Check permission with audit logging
static function checkPermission(permission : String) : boolean {
var user = SessionUtil.CurrentUser
if (user == null) {
LOG.warn("Permission check failed: No user in session")
return false
}
var hasPermission = RoleManager.hasPermission(user, permission)
if (!hasPermission) {
LOG.warn("Permission denied: ${permission} for user ${user.UserName}")
auditPermissionDenial(user, permission)
}
return hasPermission
}
// Require permission (throws if denied)
static function requirePermission(permission : String) {
if (!checkPermission(permission)) {
throw new SecurityException("Permission denied: ${permission}")
}
}
// Check entity-level permission
static function canAccessEntity(entity : KeyableBean, operation : String) : boolean {
var user = SessionUtil.CurrentUser
if (user == null) {
return false
}
// Check ownership
if (isOwner(user, entity)) {
return true
}
// Check hierarchical access
if (hasHierarchicalAccess(user, entity)) {
return true
}
// Check role-based access
var permission = "${entity.IntrinsicType.Name}_${operation}"
return checkPermission(permission)
}
private static function isOwner(user : User, entity : KeyableBean) : boolean {
// Check if user created or is assigned to entity
if (entity typeis Policy) {
return entity.CreateUser == user
} else if (entity typeis Claim) {
return entity.AssignedUser == user
}
return false
}
private static function hasHierarchicalAccess(user : User, entity : KeyableBean) : boolean {
// Check organizational hierarchy
if (entity typeis Policy) {
var policyOrg = entity.ProducerCodeOfRecord?.Organization
return user.Organization == policyOrg || isParentOrg(user.Organization, policyOrg)
}
return false
}
private static function auditPermissionDenial(user : User, permission : String) {
// Log to audit trail
gw.api.audit.AuditLogger.log(
"PERMISSION_DENIED",
"User ${user.UserName} denied permission: ${permission}",
user.PublicID
)
}
}
```
### Step 5: Row-Level Security
```gosu
// Row-level security implementation
package gw.security.rls
uses gw.api.database.Query
uses gw.api.web.SessionUtil
class RowLevelSecurity {
// Apply security filters to queries
static function applySecurityFilter(query : Query) : Query {
var user = SessionUtil.CurrentUser
if (user == null || user.hasRole(Role.get("SystemAdmin"))) {
return query // No filtering for system admins
}
var entityType = query.getTargetType()
if (entityType == Policy) {
return applyPolicySecurityFilter(query as Query, user) as Query
} else if (entityType == Claim) {
return applyClaimSecurityFilter(query as Query, user) as Query
} else if (entityType == Account) {
return applyAccountSecurityFilter(query as Query, user) as Query
}
return query
}
private static function applyPolicySecurityFilter(
query : Query,
user : User
) : Query {
// Filter by user's organization or producer code
var userProducerCodes = user.ProducerCodes.map(\pc -> pc.Code)
if (!userProducerCodes.Empty) {
query.join(Policy#ProducerCodeOfRecord)
.compareIn(ProducerCode#Code, userProducerCodes)
}
return query
}
private static function applyClaimSecurityFilter(
query : Query,
user : User
) : Query {
// Filter by assigned user or group
var userGroups = user.GroupUsers.map(\gu -> gu.Group)
query.or(\orClause -> {
orClause.compare(Claim#AssignedUser, Equals, user)
if (!userGroups.Empty) {
orClause.compareIn(Claim#AssignedGroup, userGroups)
}
})
return query
}
private static function applyAccountSecurityFilter(
query : Query,
user : User
) : Query {
// Filter by producer code assignment
var userProducerCodes = user.ProducerCodes.map(\pc -> pc.PublicID)
if (!userProducerCodes.Empty) {
query.subselect(Account#ID, CompareIn,
Query.make(AccountProducerCode)
.compareIn(AccountProducerCode#ProducerCode, userProducerCodes)
.subselect(AccountProducerCode#Account, CompareIn, Account#ID)
)
}
return query
}
}
// Secured query helper
class SecuredQuery {
static function make(type : Type) : Query {
var query = Query.make(type)
return RowLevelSecurity.applySecurityFilter(query)
}
}
// Usage
class PolicyService {
static function findPoliciesForCurrentUser() : List {
// Automatically applies row-level security
return SecuredQuery.make(Policy)
.compare(Policy#Status, Equals, PolicyStatus.TC_INFORCE)
.select()
.toList()
}
}
```
### Step 6: API Authorization Middleware
```typescript
// API authorization middleware
import { Request, Response, NextFunction } from 'express';
interface SecurityContext {
userId: string;
roles: string[];
apiRoles: string[];
organizationId: string;
producerCodes: string[];
}
// Extract security context from JWT
function extractSecurityContext(token: JWTPayload): SecurityContext {
return {
userId: token.sub,
roles: token.roles || [],
apiRoles: token.api_roles || [],
organizationId: token.org_id,
producerCodes: token.producer_codes || []
};
}
// Require specific API role
function requireApiRole(...requiredRoles: string[]) {
return (req: Request, res: Response, next: NextFunction) => {
const context = (req as any).securityContext as SecurityContext;
if (!context) {
return res.status(401).json({ error: 'Unauthorized' });
}
const hasRequiredRole = requiredRoles.some(role =>
context.apiRoles.includes(role)
);
if (!hasRequiredRole) {
return res.status(403).json({
error: 'Forbidden',
message: 'Insufficient API role permissions',
requiredRoles,
userRoles: context.apiRoles
});
}
next();
};
}
// Row-level security filter for API responses
function applySecurityFilter(
data: T[],
context: SecurityContext,
filterFn: (item: T, context: SecurityContext) => boolean
): T[] {
if (context.roles.includes('SystemAdmin')) {
return data;
}
return data.filter(item => filterFn(item, context));
}
// Usage in routes
app.get('/api/policies',
authMiddleware,
requireApiRole('pc_policy_read', 'pc_policy_admin'),
async (req, res) => {
const context = (req as any).securityContext;
let policies = await guidewireClient.getPolicies();
// Apply row-level security
policies = applySecurityFilter(policies, context, (policy, ctx) => {
return ctx.producerCodes.includes(policy.producerCode) ||
ctx.organizationId === policy.organizationId;
});
res.json(policies);
}
);
```
## Role Matrix
| Role | PolicyCenter | ClaimCenter | BillingCenter |
|------|-------------|-------------|---------------|
| System Admin | Full Access | Full Access | Full Access |
| Underwriter | Submissions, Quotes | Read Only | Read Only |
| Claims Adjuster | Read Only | Claims, Payments | Read Only |
| Billing Admin | Read Only | Read Only | Full Access |
| Agent | Submissions, Read | FNOL Only | Read Only |
| Auditor | Read Only | Read Only | Read Only |
## Best Practices
| Practice | Description |
|----------|-------------|
| Least Privilege | Grant minimum necessary permissions |
| Role Separation | Separate roles by function, not convenience |
| Regular Audits | Review role assignments quarterly |
| Service Accounts | Use dedicated accounts for integrations |
| API Role Scoping | Scope API roles to specific endpoints |
## Output
- API role configuration
- Service account setup
- User role management
- Custom permission framework
- Row-level security
- Authorization middleware
## Resources
- [Guidewire Security Documentation](https://docs.guidewire.com/security/)
- [API Role Configuration](https://docs.guidewire.com/cloud/)
- [Authentication Architecture](https://docs.guidewire.com/cloud/pc/202503/cloudapica/)
## Next Steps
For migration strategies, see `guidewire-migration-deep-dive`.