- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
22 KiB
22 KiB
Security by Design
Навигация
Принципы Security by Design
1. Secure by Default
- Безопасные настройки по умолчанию
- Минимальные права доступа
- Защита от случайных ошибок
2. Fail Secure
- При отказе система переходит в безопасное состояние
- Блокировка доступа при ошибках
- Логирование всех событий безопасности
3. Security as Code
- Безопасность как часть кода
- Автоматизированные проверки безопасности
- Версионирование политик безопасности
Моделирование угроз
STRIDE Model
- Spoofing (Подмена)
- Tampering (Изменение)
- Repudiation (Отказ)
- Information Disclosure (Раскрытие информации)
- Denial of Service (Отказ в обслуживании)
- Elevation of Privilege (Повышение привилегий)
Пример Threat Model:
# threat-model.yml
application: "E-commerce Platform"
components:
- name: "User Authentication"
threats:
- type: "Spoofing"
description: "User impersonation"
mitigations:
- "Strong password policy"
- "Multi-factor authentication"
- name: "Payment Processing"
threats:
- type: "Tampering"
description: "Payment data modification"
mitigations:
- "Data encryption"
- "Digital signatures"
Архитектура безопасности
1. Zero Trust Architecture
Принцип: "Никогда не доверяй, всегда проверяй"
@Component
public class ZeroTrustFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// проверяем каждую аутентификацию
if (!isAuthenticated(httpRequest)) {
throw new AuthenticationException("Authentication required");
}
// проверяем каждую авторизацию
if (!isAuthorized(httpRequest)) {
throw new AuthorizationException("Access denied");
}
// проверяем устройство
if (!isDeviceTrusted(httpRequest)) {
throw new SecurityException("Untrusted device");
}
chain.doFilter(request, response);
}
}
2. Microsegmentation
Принцип: Разделение сети на мелкие сегменты
# network-policy.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: order-service-policy
spec:
podSelector:
matchLabels:
app: order-service
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: payment-service
ports:
- protocol: TCP
port: 8080
Аутентификация и авторизация
Аутентификация
1. Password-based Authentication
@Service
public class AuthenticationService {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserRepository userRepository;
public AuthenticationResult authenticate(String username, String password) {
User user = userRepository.findByUsername(username);
if (user == null) {
return AuthenticationResult.failure("User not found");
}
if (!passwordEncoder.matches(password, user.getPasswordHash())) {
return AuthenticationResult.failure("Invalid password");
}
if (!user.isActive()) {
return AuthenticationResult.failure("User account is disabled");
}
return AuthenticationResult.success(user);
}
}
2. Multi-Factor Authentication (MFA)
@Service
public class MFAService {
@Autowired
private TOTPGenerator totpGenerator;
@Autowired
private SMSService smsService;
public void enableMFA(Long userId, String phoneNumber) {
String secret = totpGenerator.generateSecret();
userRepository.updateMFASecret(userId, secret);
userRepository.updatePhoneNumber(userId, phoneNumber);
}
public boolean verifyMFA(Long userId, String code) {
User user = userRepository.findById(userId);
String secret = user.getMFASecret();
return totpGenerator.verifyCode(secret, code);
}
public void sendSMS(Long userId, String code) {
User user = userRepository.findById(userId);
smsService.sendSMS(user.getPhoneNumber(), "Your verification code: " + code);
}
}
3. OAuth 2.0 / OpenID Connect
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(customOAuth2UserService)
)
)
.authorizeHttpRequests(authz -> authz
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
Авторизация
1. Role-Based Access Control (RBAC)
@Entity
public class User {
@Id
private Long id;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
}
@Entity
public class Role {
@Id
private Long id;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "role_permissions",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id")
)
private Set<Permission> permissions = new HashSet<>();
}
2. Attribute-Based Access Control (ABAC)
@Component
public class ABACPolicyEngine {
public boolean evaluate(Policy policy, AccessRequest request) {
// проверяем субъект
if (!policy.getSubject().matches(request.getSubject())) {
return false;
}
// проверяем ресурс
if (!policy.getResource().matches(request.getResource())) {
return false;
}
// проверяем действие
if (!policy.getAction().matches(request.getAction())) {
return false;
}
// проверяем контекст
if (!policy.getContext().matches(request.getContext())) {
return false;
}
return true;
}
}
// Пример политики
Policy policy = Policy.builder()
.subject("role:manager")
.resource("department:finance")
.action("read")
.context("time:business_hours")
.build();
3. JWT Tokens
@Service
public class JWTService {
private final String secretKey = "mySecretKey";
private final int jwtExpiration = 86400000; // 24 hours
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles", userDetails.getAuthorities());
claims.put("userId", userDetails.getUsername());
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
.signWith(SignatureAlgorithm.HS512, secretKey)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
Безопасность API
Лучшие практики безопасности API
1. Input Validation
@RestController
@Validated
public class UserController {
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
// валидация выполняется автоматически через @Valid
User user = userService.createUser(request);
return ResponseEntity.ok(user);
}
}
public class CreateUserRequest {
@NotBlank(message = "Username is required")
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
private String username;
@NotBlank(message = "Email is required")
@Email(message = "Email must be valid")
private String email;
@NotBlank(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters")
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$",
message = "Password must contain at least one uppercase letter, one lowercase letter, one number and one special character")
private String password;
}
2. Rate Limiting
@Component
public class RateLimitingFilter implements Filter {
private final Map<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String clientId = getClientId(httpRequest);
RateLimiter rateLimiter = rateLimiters.computeIfAbsent(clientId,
k -> RateLimiter.create(10.0)); // 10 запросов в секунду
if (!rateLimiter.tryAcquire()) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(429); // Too Many Requests
httpResponse.getWriter().write("Rate limit exceeded");
return;
}
chain.doFilter(request, response);
}
}
3. API Versioning
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 {
@GetMapping("/{id}")
public UserV1 getUser(@PathVariable Long id) {
return userService.getUserV1(id);
}
}
@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
@GetMapping("/{id}")
public UserV2 getUser(@PathVariable Long id) {
return userService.getUserV2(id);
}
}
Безопасность API Gateway
# api-gateway-security.yml
apiVersion: networking.istio.io/v1alpha3
kind: AuthorizationPolicy
metadata:
name: api-gateway-policy
spec:
selector:
matchLabels:
app: api-gateway
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/api-gateway"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
- from:
- source:
principals: ["cluster.local/ns/default/sa/admin-service"]
to:
- operation:
methods: ["*"]
paths: ["/admin/*"]
Безопасность данных
Классификация данных
1. Data Sensitivity Levels
- Public — общедоступные данные
- Internal — внутренние данные
- Confidential — конфиденциальные данные
- Restricted — ограниченные данные
@Entity
public class User {
@Id
private Long id;
@Column(name = "username")
@DataClassification(level = DataClassification.Level.INTERNAL)
private String username;
@Column(name = "email")
@DataClassification(level = DataClassification.Level.CONFIDENTIAL)
private String email;
@Column(name = "ssn")
@DataClassification(level = DataClassification.Level.RESTRICTED)
@Encrypted
private String ssn;
}
2. Data Masking
@Service
public class DataMaskingService {
public User maskUserData(User user, UserRole requesterRole) {
User maskedUser = new User();
maskedUser.setId(user.getId());
switch (requesterRole) {
case ADMIN:
// админы видят все данные
maskedUser.setEmail(user.getEmail());
maskedUser.setSsn(user.getSsn());
break;
case MANAGER:
// менеджеры видят частично замаскированные данные
maskedUser.setEmail(maskEmail(user.getEmail()));
maskedUser.setSsn(maskSSN(user.getSsn()));
break;
case USER:
// обычные пользователи видят только базовую информацию
maskedUser.setEmail(maskEmail(user.getEmail()));
maskedUser.setSsn("***-**-****");
break;
}
return maskedUser;
}
private String maskEmail(String email) {
String[] parts = email.split("@");
String username = parts[0];
String domain = parts[1];
if (username.length() <= 2) {
return "*@" + domain;
}
return username.substring(0, 2) + "*".repeat(username.length() - 2) + "@" + domain;
}
private String maskSSN(String ssn) {
return "***-**-" + ssn.substring(ssn.length() - 4);
}
}
Шифрование данных
1. Encryption at Rest
@Entity
public class PaymentCard {
@Id
private Long id;
@Column(name = "card_number")
@Convert(converter = EncryptedStringConverter.class)
private String cardNumber;
@Column(name = "cvv")
@Convert(converter = EncryptedStringConverter.class)
private String cvv;
}
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
@Autowired
private EncryptionService encryptionService;
@Override
public String convertToDatabaseColumn(String attribute) {
return encryptionService.encrypt(attribute);
}
@Override
public String convertToEntityAttribute(String dbData) {
return encryptionService.decrypt(dbData);
}
}
2. Encryption in Transit
@Configuration
public class SSLConfig {
@Bean
public RestTemplate restTemplate() throws Exception {
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (certificate, authType) -> true)
.build();
HttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
Соответствие требованиям
GDPR (Общий регламент по защите данных)
1. Data Subject Rights
@Service
public class GDPRService {
public void handleDataSubjectRequest(DataSubjectRequest request) {
switch (request.getType()) {
case ACCESS:
provideDataAccess(request.getSubjectId());
break;
case RECTIFICATION:
rectifyData(request.getSubjectId(), request.getData());
break;
case ERASURE:
eraseData(request.getSubjectId());
break;
case PORTABILITY:
provideDataPortability(request.getSubjectId());
break;
}
}
private void eraseData(Long subjectId) {
// удаляем персональные данные
userRepository.deletePersonalData(subjectId);
// логируем удаление
auditService.logDataErasure(subjectId);
// уведомляем заинтересованные системы
notificationService.notifyDataErasure(subjectId);
}
}
2. Consent Management
@Entity
public class Consent {
@Id
private Long id;
private Long userId;
private String purpose;
private ConsentStatus status;
private LocalDateTime givenAt;
private LocalDateTime withdrawnAt;
public boolean isValid() {
return status == ConsentStatus.GIVEN && withdrawnAt == null;
}
}
@Service
public class ConsentService {
public void giveConsent(Long userId, String purpose) {
Consent consent = new Consent();
consent.setUserId(userId);
consent.setPurpose(purpose);
consent.setStatus(ConsentStatus.GIVEN);
consent.setGivenAt(LocalDateTime.now());
consentRepository.save(consent);
}
public void withdrawConsent(Long userId, String purpose) {
Consent consent = consentRepository.findByUserIdAndPurpose(userId, purpose);
if (consent != null) {
consent.setStatus(ConsentStatus.WITHDRAWN);
consent.setWithdrawnAt(LocalDateTime.now());
consentRepository.save(consent);
}
}
}
PCI DSS (Стандарт безопасности данных индустрии платежных карт)
1. Card Data Protection
@Service
public class PCIService {
public String tokenizeCard(String cardNumber) {
// генерируем токен вместо хранения номера карты
String token = UUID.randomUUID().toString();
// сохраняем токен в безопасном хранилище
secureStorage.storeToken(token, cardNumber);
return token;
}
public String detokenizeCard(String token) {
// получаем номер карты по токену
return secureStorage.getCardByToken(token);
}
public boolean validateCard(String cardNumber) {
// проверяем номер карты по алгоритму Луна
return luhnAlgorithm.validate(cardNumber);
}
}
2. Secure Payment Processing
@Service
public class PaymentService {
@Transactional
public PaymentResult processPayment(PaymentRequest request) {
// валидируем данные карты
if (!validateCardData(request.getCardData())) {
return PaymentResult.failure("Invalid card data");
}
// токенизируем данные карты
String token = tokenizeCard(request.getCardData().getNumber());
// обрабатываем платеж
PaymentResult result = paymentProcessor.processPayment(request);
// логируем транзакцию
auditService.logPaymentTransaction(request, result);
return result;
}
}
SOX (Закон Сарбейнса-Оксли)
1. Financial Data Controls
@Service
public class FinancialControlService {
public void validateFinancialTransaction(FinancialTransaction transaction) {
// проверяем авторизацию
if (!isAuthorized(transaction.getAmount())) {
throw new AuthorizationException("Transaction amount exceeds authorization limit");
}
// проверяем дублирование
if (isDuplicateTransaction(transaction)) {
throw new DuplicateTransactionException("Duplicate transaction detected");
}
// проверяем целостность данных
if (!validateDataIntegrity(transaction)) {
throw new DataIntegrityException("Data integrity check failed");
}
}
public void auditFinancialData() {
// аудит финансовых данных
List<FinancialTransaction> transactions = getTransactionsForAudit();
for (FinancialTransaction transaction : transactions) {
validateTransaction(transaction);
logAuditTrail(transaction);
}
}
}
Заключение
Security by Design обеспечивает встроенную безопасность на всех уровнях приложения:
- Принципы безопасности — Secure by Default, Fail Secure, Security as Code
- Моделирование угроз — STRIDE модель для выявления рисков
- Архитектура безопасности — Zero Trust, Microsegmentation
- Аутентификация и авторизация — MFA, RBAC, ABAC, JWT
- Безопасность API — Валидация, Rate Limiting, Versioning
- Безопасность данных — Классификация, Маскирование, Шифрование
- Соответствие требованиям — GDPR, PCI DSS, SOX
Интеграция этих принципов в процесс разработки обеспечивает надежную защиту приложения от угроз безопасности.