- name
- access-control-policy
- description
- Identity and access management: RBAC, least privilege, MFA, quarterly reviews per ISO 27001 A.5.15, A.8.2, A.8.3
# Access Control Policy Skill
## Purpose
This skill provides systematic guidance for implementing zero-trust access control within the CIA platform, ensuring identity-centric security through role-based access control (RBAC), least privilege principle, multi-factor authentication (MFA), and regular access reviews per ISO 27001 A.5.15, A.8.2, and A.8.3.
## When to Use This Skill
Apply this skill when:
- ✅ Implementing authentication and authorization systems
- ✅ Designing role-based access control (RBAC) models
- ✅ Configuring MFA for privileged accounts
- ✅ Establishing access review procedures
- ✅ Implementing least privilege access controls
- ✅ Setting up identity federation (AWS IAM Identity Center, GitHub SSO)
- ✅ Conducting quarterly access audits
- ✅ Managing privileged access (break-glass procedures)
Do NOT skip for:
- ❌ Internal-only systems (still require authentication)
- ❌ Development environments (may contain production data)
- ❌ Administrative interfaces (highest risk, require MFA)
- ❌ API access (requires API keys, OAuth tokens)
## Zero-Trust Access Architecture
### Identity-Centric Design Principle
```mermaid
graph TD
subgraph Identity["🔐 Identity Provider"]
PRIMARY["Primary IdP<br/>🔐 MFA Enforced<br/>Central Authentication"]
end
subgraph Cloud["☁️ Cloud Infrastructure"]
IDC["AWS Identity Center<br/>🔐 SSO + MFA"]
IAM["IAM Roles<br/>🛡️ Least Privilege"]
ACCOUNTS["AWS Accounts<br/>📊 Federated Access"]
end
subgraph Dev["📝 Development"]
GITHUB["GitHub Organization<br/>🔐 MFA Required"]
CICD["CI/CD Pipeline<br/>🔑 Service Accounts"]
end
subgraph Business["💼 Business Systems"]
FINANCE["Financial Systems<br/>💰 Hardware Token"]
MARKETING["Marketing Tools<br/>📱 Platform MFA"]
SECURITY["Security Tools<br/>🛡️ Enhanced MFA"]
end
PRIMARY --> IDC
PRIMARY --> GITHUB
PRIMARY --> FINANCE
IDC --> IAM
IDC --> ACCOUNTS
GITHUB --> CICD
style Identity fill:#1565C0
style Cloud fill:#4CAF50
style Dev fill:#FF9800
style Business fill:#7B1FA2
```
### Access Control Matrix
Integration with [Classification Framework](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md):
| Asset Category | Classification | Access Method | MFA Requirement | Session Timeout | Review Frequency |
|---------------|----------------|---------------|-----------------|-----------------|------------------|
| **RESTRICTED Data** | Extreme | Hardware MFA + Zero Trust | FIDO2 + Backup | 1 hour | Monthly |
| **Cloud Infrastructure** | Very High | Identity Center SSO | Hardware + TOTP | 4 hours | Monthly |
| **Development Platform** | High | Platform MFA + SSH Keys | TOTP + SSH Cert | 8 hours | Quarterly |
| **Financial Systems** | Very High | Provider MFA | Hardware Token | 1 hour | Monthly |
| **Business Intelligence** | Moderate | SSO Integration | TOTP | 24 hours | Semi-Annual |
| **Marketing Platforms** | Public/Internal | Platform Native | Platform MFA | 7 days | Annual |
## Role-Based Access Control (RBAC)
### RBAC Implementation in Spring Security
**Permission Levels and Scope**:
```java
/**
* RBAC role hierarchy for CIA platform
*
* Implements ISO 27001 A.8.2 (Privileged access rights)
*
* @see <a href="https://github.com/Hack23/ISMS-PUBLIC/blob/main/Access_Control_Policy.md">Access Control Policy</a>
*/
@Configuration
@EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true
)
public class SecurityConfig {
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
// RBAC hierarchy: higher roles inherit lower role permissions
hierarchy.setHierarchy(
"ROLE_ADMIN > ROLE_PARTY_ANALYST\n" +
"ROLE_PARTY_ANALYST > ROLE_AUTHENTICATED_USER\n" +
"ROLE_AUTHENTICATED_USER > ROLE_GUEST"
);
return hierarchy;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
// PUBLIC: No authentication required
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/", "/login", "/register").permitAll()
// INTERNAL: Authentication required
.requestMatchers("/api/internal/**").authenticated()
// CONFIDENTIAL: Specific roles required
.requestMatchers("/api/party-financial/**")
.hasRole("PARTY_ANALYST")
// RESTRICTED: Admin only with MFA
.requestMatchers("/api/admin/**")
.hasRole("ADMIN")
.access("@mfaVerifier.isMfaAuthenticated(authentication)")
// Default: Require authentication
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
// Session timeout based on access level
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
)
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
);
return http.build();
}
}
```
### Role Definitions
| Role | Scope | Permissions | Use Cases | Access Pattern |
|------|-------|-------------|-----------|----------------|
| **ROLE_ADMIN** | System-wide | Full access, user management, security config | Emergency operations, security incidents | Break-glass only |
| **ROLE_PARTY_ANALYST** | Party data | Read/write party financial records, voting analysis | Political analysis, report generation | Daily operations |
| **ROLE_AUTHENTICATED_USER** | Public + internal | Read public data, basic operations | Registered users, researchers | Standard usage |
| **ROLE_GUEST** | Public only | Read public voting records, party information | Anonymous visitors | Public access |
### Least Privilege Enforcement
```java
/**
* Service-level access control with least privilege
*
* Implements ISO 27001 A.8.2 - Privileged access rights
*/
@Service
public class PartyFinancialService {
private final AuditLogger auditLogger;
private final PartyFinancialRepository repository;
// CONFIDENTIAL data requires specific role
@PreAuthorize("hasRole('PARTY_ANALYST') or hasRole('ADMIN')")
@PostAuthorize("returnObject.userId == authentication.principal.username or hasRole('ADMIN')")
public PartyFinancialRecord getFinancialRecord(Long recordId) {
auditLogger.logAccess(
"CONFIDENTIAL",
"party_financial_record",
recordId,
SecurityContextHolder.getContext().getAuthentication().getName()
);
return repository.findById(recordId)
.orElseThrow(() -> new AccessDeniedException("Record not found or access denied"));
}
// Write operations require explicit role check
@PreAuthorize("hasRole('PARTY_ANALYST')")
@Audited(action = "CREATE", resourceType = "party_financial_record")
public PartyFinancialRecord createRecord(PartyFinancialRecord record) {
// Validation and business logic
return repository.save(record);
}
// Admin-only operations with MFA verification
@PreAuthorize("hasRole('ADMIN') and @mfaVerifier.isMfaAuthenticated(authentication)")
@Audited(action = "DELETE", resourceType = "party_financial_record", severity = "HIGH")
public void deleteRecord(Long recordId) {
auditLogger.logPrivilegedAction(
"DELETE_FINANCIAL_RECORD",
recordId,
SecurityContextHolder.getContext().getAuthentication().getName()
);
repository.deleteById(recordId);
}
}
```
## Multi-Factor Authentication (MFA)
### MFA Requirements by Access Level
```mermaid
graph TD
subgraph Access["🔐 Access Levels"]
ADMIN["Admin Access<br/>🚨 Break-Glass"]
PRIVILEGED["Privileged Data<br/>💰 Financial Systems"]
STANDARD["Standard Access<br/>📊 Business Data"]
PUBLIC["Public Access<br/>🌐 No Authentication"]
end
subgraph MFA["🔑 MFA Methods"]
HARDWARE["Hardware Token<br/>🔐 FIDO2, YubiKey"]
TOTP["TOTP App<br/>📱 Authenticator"]
SMS["SMS Backup<br/>📞 Secondary"]
PLATFORM["Platform Native<br/>🏢 GitHub, AWS"]
end
subgraph Verify["✅ Verification"]
CONTINUOUS["Continuous Verification<br/>⏱️ Session Monitoring"]
PERIODIC["Periodic Re-auth<br/>🔄 Timeout-Based"]
ONETIME["One-Time Verification<br/>✅ Login Only"]
end
ADMIN --> HARDWARE
PRIVILEGED --> HARDWARE
PRIVILEGED --> TOTP
STANDARD --> TOTP
STANDARD --> PLATFORM
HARDWARE --> CONTINUOUS
TOTP --> PERIODIC
PLATFORM --> ONETIME
style Access fill:#1565C0
style MFA fill:#FF9800
style Verify fill:#4CAF50
```
### MFA Implementation Example
```java
/**
* MFA verification service
*
* Implements ISO 27001 A.5.17 - Authentication information
*/
@Service
public class MfaVerificationService {
private final TotpService totpService;
private final AuditLogger auditLogger;
/**
* Verify MFA token for privileged operations
*
* @param authentication Current authentication
* @return true if MFA verified within acceptable window
*/
public boolean isMfaAuthenticated(Authentication authentication) {
if (authentication == null || !authentication.isAuthenticated()) {
return false;
}
Object principal = authentication.getPrincipal();
if (!(principal instanceof UserDetails)) {
return false;
}
UserDetails user = (UserDetails) principal;
String username = user.getUsername();
// Check if MFA verified within last hour
LocalDateTime mfaVerifiedAt = getMfaVerificationTime(username);
LocalDateTime now = LocalDateTime.now();
if (mfaVerifiedAt == null ||
Duration.between(mfaVerifiedAt, now).toHours() >= 1) {
auditLogger.logMfaRequired(username);
return false;
}
return true;
}
/**
* Verify TOTP code and update verification timestamp
*/
public boolean verifyTotpCode(String username, String totpCode) {
boolean isValid = totpService.verifyCode(username, totpCode);
if (isValid) {
updateMfaVerificationTime(username, LocalDateTime.now());
auditLogger.logMfaSuccess(username);
} else {
auditLogger.logMfaFailure(username);
}
return isValid;
}
/**
* Require MFA re-verification for privileged operation
*/
public void requireMfaReVerification(String username) {
clearMfaVerificationTime(username);
auditLogger.logMfaRequired(username, "PRIVILEGED_OPERATION");
}
}
/**
* MFA controller for verification flow
*/
@RestController
@RequestMapping("/api/auth/mfa")
public class MfaController {
private final MfaVerificationService mfaService;
@PostMapping("/verify")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<MfaVerificationResponse> verifyMfa(
@RequestBody @Valid MfaVerificationRequest request,
Authentication authentication) {
String username = authentication.getName();
boolean isValid = mfaService.verifyTotpCode(username, request.getTotpCode());
if (isValid) {
return ResponseEntity.ok(new MfaVerificationResponse(true, "MFA verified"));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new MfaVerificationResponse(false, "Invalid MFA code"));
}
}
@GetMapping("/status")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<MfaStatusResponse> getMfaStatus(Authentication authentication) {
String username = authentication.getName();
boolean isMfaVerified = mfaService.isMfaAuthenticated(authentication);
return ResponseEntity.ok(new MfaStatusResponse(isMfaVerified));
}
}
```
### Session Management by Classification
```java
/**
* Dynamic session timeout based on data classification
*/
@Configuration
public class SessionConfig {
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
/**
* Configure session timeout based on access level
*/
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
/**
* Session timeout customizer
*/
@Component
public class SessionTimeoutCustomizer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Default session timeout: 30 minutes
servletContext.setSessionTimeout(30);
}
}
/**
* Dynamic timeout adjustment based on role
*/
@Component
public class DynamicSessionTimeoutManager {
public int getSessionTimeout(Authentication authentication) {
Collection<? extends GrantedAuthority> authorities =
authentication.getAuthorities();
// ADMIN: 1 hour (RESTRICTED data access)
if (authorities.stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
return 60;
}
// PARTY_ANALYST: 4 hours (CONFIDENTIAL data access)
if (authorities.stream().anyMatch(a -> a.getAuthority().equals("ROLE_PARTY_ANALYST"))) {
return 240;
}
// AUTHENTICATED_USER: 8 hours (INTERNAL data access)
if (authorities.stream().anyMatch(a -> a.getAuthority().equals("ROLE_AUTHENTICATED_USER"))) {
return 480;
}
// Default: 30 minutes
return 30;
}
}
}
```
## Quarterly Access Reviews
### Access Review Procedure
```mermaid
graph TD
View on GitHub