28 KiB
HiveOps Config Server Implementation Plan
Context
This plan addresses the implementation of a centralized configuration server (hiveops-config) for the HiveOps microservices ecosystem. The goal is to provide externalized, version-controlled configuration management using Spring Cloud Config Server.
Motivation: Currently, each microservice (hiveops-mgmt, hiveops-auth, hiveops-incident) manages its configuration independently through application.yml files and environment variables. This creates challenges:
- Configuration drift between environments (dev, staging, prod)
- No centralized view of all service configurations
- Difficult to audit configuration changes
- No version control for configuration history
- Shared settings (like JWT secrets) duplicated across services
Solution: Implement Spring Cloud Config Server to centralize configuration in a Git repository with environment-specific profiles, enabling version control, audit trails, and consistent configuration across all services.
Existing Microservices:
- hiveops-mgmt (port 8080): License management, internal user authentication
- hiveops-incident (port 8081): Incident management and workflow
- hiveops-auth (port 8082): Customer authentication with MFA
New Service:
- hiveops-config (port 8083): Centralized configuration server
Architecture Decision
Spring Cloud Config Server with Git Backend
Approach: Centralized configuration with local/remote Git repository storage
Configuration Flow:
Git Repository (config-repo/)
├── application.yml # Shared defaults
├── hiveops-mgmt.yml # mgmt-specific config
├── hiveops-mgmt-dev.yml # mgmt dev profile
├── hiveops-mgmt-prod.yml # mgmt prod profile
├── hiveops-auth.yml # auth-specific config
├── hiveops-auth-dev.yml # auth dev profile
├── hiveops-auth-prod.yml # auth prod profile
├── hiveops-incident.yml # incident-specific config
├── hiveops-incident-dev.yml # incident dev profile
└── hiveops-incident-prod.yml # incident prod profile
↓
hiveops-config (Spring Cloud Config Server)
- Serves configuration over HTTP
- Port 8083
- Secure endpoints with HTTP Basic Auth
- Health checks and monitoring
↓
Client Services (mgmt, incident, auth)
- Bootstrap phase: connect to config server
- Load configuration before application startup
- Support for config refresh without restart (@RefreshScope)
Benefits:
- Version control for all configurations (Git history)
- Environment-specific profiles (dev, prod, staging)
- Centralized security settings
- Dynamic configuration updates without redeployment
- Audit trail via Git commits
- Easy rollback to previous configurations
- Shared configuration elimination (e.g., JWT secrets defined once)
Project Structure
hiveops-config/
├── src/main/
│ ├── java/com/hiveops/config/
│ │ ├── HiveopsConfigServerApplication.java # Main class with @EnableConfigServer
│ │ └── config/
│ │ └── SecurityConfig.java # HTTP Basic Auth for config endpoints
│ │
│ └── resources/
│ ├── application.yml # Config server settings (dev)
│ └── application-prod.yml # Prod profile (remote git)
│
├── config-repo/ # Local Git repository for configurations
│ ├── application.yml # Shared defaults
│ ├── hiveops-mgmt.yml
│ ├── hiveops-mgmt-dev.yml
│ ├── hiveops-mgmt-prod.yml
│ ├── hiveops-auth.yml
│ ├── hiveops-auth-dev.yml
│ ├── hiveops-auth-prod.yml
│ ├── hiveops-incident.yml
│ ├── hiveops-incident-dev.yml
│ ├── hiveops-incident-prod.yml
│ └── .gitignore
│
├── devops-scripts/
│ ├── build-and-push.sh
│ ├── deploy.sh
│ └── docker/
│ └── .env.example
│
├── Dockerfile # Multi-stage Alpine build
├── docker-compose.yml # Dev environment
├── docker-compose.prod.yml # Prod deployment
├── pom.xml
└── README.md
Spring Cloud Config Server Implementation
Key Dependencies (pom.xml)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.1</version>
</parent>
<properties>
<java.version>21</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>
<dependencies>
<!-- Spring Cloud Config Server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- Spring Boot Actuator (health checks) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring Security (HTTP Basic Auth) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Main Application Class
package com.hiveops.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class HiveopsConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(HiveopsConfigServerApplication.class, args);
}
}
Security Configuration (HTTP Basic Auth)
package com.hiveops.config.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Value("${config.security.username}")
private String username;
@Value("${config.security.password}")
private String password;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health", "/actuator/info").permitAll()
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.disable());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.builder()
.username(username)
.password(passwordEncoder().encode(password))
.roles("CONFIG_CLIENT")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Config Server Configuration (application.yml)
server:
port: 8083
spring:
application:
name: hiveops-config-server
cloud:
config:
server:
git:
uri: file://${user.dir}/config-repo # Dev: local repo
default-label: main
clone-on-start: true
force-pull: true
# Security credentials
config:
security:
username: ${CONFIG_USERNAME:config-user}
password: ${CONFIG_PASSWORD:changeme}
# Actuator endpoints
management:
endpoints:
web:
exposure:
include: health,info,env,refresh
endpoint:
health:
show-details: always
# Logging
logging:
level:
root: INFO
org.springframework.cloud.config: DEBUG
Production Configuration (application-prod.yml)
spring:
cloud:
config:
server:
git:
uri: ${GIT_REPO_URL} # Remote git repository URL
username: ${GIT_USERNAME}
password: ${GIT_PASSWORD}
default-label: main
clone-on-start: true
force-pull: true
timeout: 10
# Security (from environment variables)
config:
security:
username: ${CONFIG_USERNAME}
password: ${CONFIG_PASSWORD}
Configuration Repository Structure
Naming Convention
Spring Cloud Config uses this pattern:
{application}-{profile}.yml
Where:
{application}= spring.application.name from client service{profile}= spring.profiles.active from client service
Example Configurations
application.yml (shared across all services):
# Shared configuration for all HiveOps microservices
logging:
level:
root: INFO
com.hiveops: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n"
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: when-authorized
hiveops-auth-prod.yml (auth service production config):
server:
port: 8082
spring:
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:hiveops_auth}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: validate
show-sql: false
# JWT Configuration (shared secret with other services)
jwt:
secret: ${JWT_SECRET}
expiration: 86400000
refresh-expiration: 604800000
# MFA Configuration
mfa:
secret-encryption-key: ${MFA_ENCRYPTION_KEY}
totp-algorithm: SHA1
totp-digits: 6
totp-period: 30
backup-code-count: 10
# Rate Limiting
rate-limit:
ip:
capacity: 20
refill-tokens: 20
refill-duration-minutes: 1
user:
capacity: 5
refill-tokens: 5
refill-duration-minutes: 15
Client Service Integration
Required Changes in Existing Services
For each service (hiveops-mgmt, hiveops-auth, hiveops-incident):
1. Add Dependencies to pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
2. Create bootstrap.yml (loaded before application.yml):
spring:
application:
name: hiveops-auth # Change per service: hiveops-mgmt, hiveops-incident
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev}
cloud:
config:
uri: ${CONFIG_SERVER_URL:http://localhost:8083}
username: ${CONFIG_USERNAME:config-user}
password: ${CONFIG_PASSWORD:changeme}
fail-fast: true # Fail startup if config server unreachable
retry:
initial-interval: 1000
max-interval: 2000
max-attempts: 6
3. Configuration Migration Strategy:
- Keep application.yml for local defaults (fallback when config server disabled)
- Move environment-specific config to config-repo/{service}-{profile}.yml
- Secrets remain in environment variables, referenced in config files
Docker Deployment
Dockerfile (Multi-Stage Alpine Build)
Following established HiveOps pattern:
# Build stage
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
# Copy Maven files
COPY pom.xml .
COPY src ./src
# Build the application
RUN apk add --no-cache maven && \
mvn clean package -DskipTests && \
mv target/*.jar app.jar
# Runtime stage
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# Create non-root user
RUN addgroup -S hiveops && adduser -S hiveops -G hiveops
# Copy JAR from builder
COPY --from=builder /app/app.jar .
# Copy config repository (for development)
COPY config-repo ./config-repo
# Initialize git in config-repo
RUN apk add --no-cache git && \
cd config-repo && \
git init && \
git config user.email "config@hiveops.com" && \
git config user.name "Config Server" && \
git add . && \
git commit -m "Initial commit" || true
# Change ownership
RUN chown -R hiveops:hiveops /app
# Switch to non-root user
USER hiveops
# Expose port
EXPOSE 8083
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8083/actuator/health || exit 1
# Run application
ENTRYPOINT ["java", "-jar", "app.jar"]
docker-compose.yml (Development)
version: '3.8'
services:
hiveops-config:
build: .
container_name: hiveops-config-dev
ports:
- "8083:8083"
environment:
- SPRING_PROFILES_ACTIVE=dev
- CONFIG_USERNAME=config-user
- CONFIG_PASSWORD=dev-password
volumes:
- ./config-repo:/app/config-repo
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- hiveops-network
networks:
hiveops-network:
driver: bridge
docker-compose.prod.yml (Production)
version: '3.8'
services:
hiveops-config:
image: ${REGISTRY_URL}/hiveops-config:${VERSION:-latest}
container_name: hiveops-config-prod
restart: unless-stopped
ports:
- "8083:8083"
environment:
- SPRING_PROFILES_ACTIVE=prod
- CONFIG_USERNAME=${CONFIG_USERNAME}
- CONFIG_PASSWORD=${CONFIG_PASSWORD}
- GIT_REPO_URL=${GIT_REPO_URL}
- GIT_USERNAME=${GIT_USERNAME}
- GIT_PASSWORD=${GIT_PASSWORD}
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- hiveops-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
hiveops-network:
external: true
DevOps Scripts (Following Standard Pattern)
build-and-push.sh
#!/bin/bash
set -e
# Configuration
SERVICE_NAME="hiveops-config"
REGISTRY_URL="${REGISTRY_URL:-registry.hiveops.com}"
# Get version from pom.xml
VERSION=$(grep -oP '<version>\K[^<]+' pom.xml | head -1)
echo "Building $SERVICE_NAME version $VERSION..."
# Build Docker image
docker build -t $SERVICE_NAME:$VERSION .
docker tag $SERVICE_NAME:$VERSION $SERVICE_NAME:latest
# Tag for registry
docker tag $SERVICE_NAME:$VERSION $REGISTRY_URL/$SERVICE_NAME:$VERSION
docker tag $SERVICE_NAME:latest $REGISTRY_URL/$SERVICE_NAME:latest
# Login to registry
if [ -n "$REGISTRY_USERNAME" ] && [ -n "$REGISTRY_PASSWORD" ]; then
echo "$REGISTRY_PASSWORD" | docker login $REGISTRY_URL -u "$REGISTRY_USERNAME" --password-stdin
fi
# Push to registry
echo "Pushing to registry..."
docker push $REGISTRY_URL/$SERVICE_NAME:$VERSION
if [ "$VERSION" != "latest" ]; then
docker push $REGISTRY_URL/$SERVICE_NAME:latest
fi
echo "Build and push completed successfully!"
echo "Image: $REGISTRY_URL/$SERVICE_NAME:$VERSION"
deploy.sh
#!/bin/bash
set -e
SERVICE_NAME="hiveops-config"
COMPOSE_FILE="docker-compose.prod.yml"
# Check if docker-compose.prod.yml exists
if [ ! -f "$COMPOSE_FILE" ]; then
COMPOSE_FILE="docker-compose.yml"
fi
echo "Deploying $SERVICE_NAME..."
# Load environment variables
if [ -f "devops-scripts/docker/.env" ]; then
export $(cat devops-scripts/docker/.env | grep -v '^#' | xargs)
fi
# Pull latest image
docker-compose -f $COMPOSE_FILE pull
# Stop and remove old containers
docker-compose -f $COMPOSE_FILE down
# Start new containers
docker-compose -f $COMPOSE_FILE up -d
# Wait for health check
echo "Waiting for service to be healthy..."
sleep 10
# Check health
if docker ps | grep -q $SERVICE_NAME; then
echo "$SERVICE_NAME deployed successfully!"
docker-compose -f $COMPOSE_FILE logs --tail=50
else
echo "Deployment failed!"
docker-compose -f $COMPOSE_FILE logs
exit 1
fi
devops-scripts/docker/.env.example
# Registry Configuration
REGISTRY_URL=registry.hiveops.com
REGISTRY_USERNAME=deploy-user
REGISTRY_PASSWORD=changeme
# Version
VERSION=1.0.0
# Config Server Security
CONFIG_USERNAME=config-user
CONFIG_PASSWORD=changeme-strong-password
# Git Repository (Production)
GIT_REPO_URL=https://github.com/hiveops/config-repo.git
GIT_USERNAME=git-user
GIT_PASSWORD=git-token
# Network
NETWORK_NAME=hiveops-network
Testing Strategy
Unit Tests
package com.hiveops.config;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class ConfigServerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(roles = "CONFIG_CLIENT")
void shouldServeConfiguration() throws Exception {
mockMvc.perform(get("/hiveops-mgmt/dev"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("hiveops-mgmt"))
.andExpect(jsonPath("$.profiles[0]").value("dev"));
}
@Test
void healthEndpointShouldBePublic() throws Exception {
mockMvc.perform(get("/actuator/health"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value("UP"));
}
@Test
void configEndpointShouldRequireAuth() throws Exception {
mockMvc.perform(get("/hiveops-mgmt/dev"))
.andExpect(status().isUnauthorized());
}
}
Critical Files to Create
New Project Files
-
/source/hiveops-src/hiveops-config/pom.xml- Maven dependencies (Spring Cloud Config Server, Security, Actuator)
-
/source/hiveops-src/hiveops-config/src/main/java/com/hiveops/config/HiveopsConfigServerApplication.java- Main class with @EnableConfigServer annotation
-
/source/hiveops-src/hiveops-config/src/main/java/com/hiveops/config/config/SecurityConfig.java- HTTP Basic Auth configuration
-
/source/hiveops-src/hiveops-config/src/main/resources/application.yml- Config server settings (dev profile with local git repo)
-
/source/hiveops-src/hiveops-config/src/main/resources/application-prod.yml- Production profile (remote git repo)
-
/source/hiveops-src/hiveops-config/config-repo/application.yml- Shared configuration for all services
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt.yml- mgmt service base configuration
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt-dev.yml- mgmt service dev profile
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt-prod.yml- mgmt service prod profile
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-auth.yml- auth service base configuration
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-auth-dev.yml- auth service dev profile
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-auth-prod.yml- auth service prod profile
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-incident.yml- incident service base configuration
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-incident-dev.yml- incident service dev profile
-
/source/hiveops-src/hiveops-config/config-repo/hiveops-incident-prod.yml- incident service prod profile
-
/source/hiveops-src/hiveops-config/config-repo/.gitignore- Ignore patterns for config repo
-
/source/hiveops-src/hiveops-config/Dockerfile- Multi-stage Alpine build
-
/source/hiveops-src/hiveops-config/docker-compose.yml- Development environment
-
/source/hiveops-src/hiveops-config/docker-compose.prod.yml- Production deployment
-
/source/hiveops-src/hiveops-config/devops-scripts/build-and-push.sh- Build and push script
-
/source/hiveops-src/hiveops-config/devops-scripts/deploy.sh- Deployment script
-
/source/hiveops-src/hiveops-config/devops-scripts/docker/.env.example- Environment variables template
-
/source/hiveops-src/hiveops-config/README.md- Documentation
-
/source/hiveops-src/hiveops-config/src/test/java/com/hiveops/config/ConfigServerIntegrationTest.java- Integration tests
Modified Files (Client Services)
For each service: hiveops-mgmt, hiveops-auth, hiveops-incident
-
pom.xml- Add spring-cloud-starter-config dependency
- Add spring-cloud-starter-bootstrap dependency
- Add spring-cloud-dependencies BOM
-
src/main/resources/bootstrap.yml(NEW)- Config server connection settings
-
devops-scripts/docker/.env.example- Add CONFIG_SERVER_URL, CONFIG_USERNAME, CONFIG_PASSWORD
-
docker-compose.ymlanddocker-compose.prod.yml- Add config server environment variables
- Add dependency on hiveops-config service
Verification Steps
1. Config Server Startup
cd /source/hiveops-src/hiveops-config
mvn spring-boot:run
# Expected log output:
# "Fetching config from local git repository at file://.../config-repo"
# "Started HiveopsConfigServerApplication in X.XXX seconds"
2. Health Check
curl http://localhost:8083/actuator/health
# Expected:
# {"status":"UP"}
3. Configuration Retrieval (Authenticated)
# Get mgmt dev configuration
curl -u config-user:changeme http://localhost:8083/hiveops-mgmt/dev
# Expected: JSON response with:
# - name: "hiveops-mgmt"
# - profiles: ["dev"]
# - propertySources: [array of config files]
4. Security Verification
# Without credentials should fail
curl http://localhost:8083/hiveops-mgmt/dev
# Expected: HTTP 401 Unauthorized
5. Client Service Integration
# Start config server
cd /source/hiveops-src/hiveops-config
mvn spring-boot:run &
# Start mgmt service with config client enabled
cd /source/hiveops-src/hiveops-mgmt
export CONFIG_SERVER_URL=http://localhost:8083
export CONFIG_USERNAME=config-user
export CONFIG_PASSWORD=changeme
mvn spring-boot:run
# Check logs for:
# "Fetching config from server at: http://localhost:8083"
# "Located environment: name=hiveops-mgmt, profiles=[dev]"
# Verify config loaded
curl http://localhost:8080/actuator/env | jq '.propertySources[] | select(.name | contains("configServer"))'
6. Docker Build and Run
# Build Docker image
cd /source/hiveops-src/hiveops-config
docker build -t hiveops-config:1.0.0 .
# Run container
docker run -d -p 8083:8083 \
-e CONFIG_USERNAME=config-user \
-e CONFIG_PASSWORD=changeme \
--name hiveops-config \
hiveops-config:1.0.0
# Test health
curl http://localhost:8083/actuator/health
Migration Strategy
Phase 1: Create Config Server (Week 1)
Tasks:
- Create hiveops-config project structure
- Implement config server with security
- Create config-repo with initial configurations (migrate from existing application.yml files)
- Deploy to dev environment
- Run tests to verify config serving
Verification:
- Config server starts successfully
- Health endpoint returns UP
- Can retrieve configurations via HTTP
- Security requires authentication
Phase 2: Integrate hiveops-mgmt (Week 2)
Tasks:
- Add Spring Cloud Config dependencies to hiveops-mgmt/pom.xml
- Create bootstrap.yml with config server connection
- Copy current application-prod.yml content to config-repo/hiveops-mgmt-prod.yml
- Test mgmt service with config server in dev environment
- Verify all existing functionality works
Rollback plan: Keep application.yml as fallback if config server unavailable
Phase 3: Integrate hiveops-auth (Week 3)
Tasks:
- Add dependencies to hiveops-auth/pom.xml
- Create bootstrap.yml
- Move auth configuration to config-repo
- Test authentication flows
- Deploy to staging
Phase 4: Integrate hiveops-incident (Week 4)
Tasks:
- Add dependencies to hiveops-incident/pom.xml
- Create bootstrap.yml
- Move incident configuration to config-repo
- Test incident workflows
- Deploy to staging
Phase 5: Production Deployment (Week 5)
Tasks:
- Create production config repository (separate Git repo on Gitea)
- Deploy config server to production
- Update all services to use prod config server
- Monitor logs and health checks
- Document configuration management process
Deployment order:
- hiveops-config (no dependencies)
- hiveops-mgmt (depends on config)
- hiveops-auth (depends on config)
- hiveops-incident (depends on config)
Security Considerations
1. Config Server Security
- HTTP Basic Authentication: Required for all config endpoints
- Strong passwords: Use environment variables, never hardcode
- HTTPS in production: Use TLS certificates
- Network isolation: Deploy in private network
2. Git Repository Security
- Private repository: Never use public repos for production configs
- Access tokens: Use personal access tokens instead of passwords
- Branch protection: Require PR reviews for config changes
- Audit logging: Track who changed what configuration
3. Secrets Management
Never commit secrets to Git
# Good: Reference environment variables
spring:
datasource:
password: ${DB_PASSWORD}
# Bad: Hardcoded secrets
spring:
datasource:
password: mySecretPassword123
4. Configuration Encryption (Future Enhancement)
Spring Cloud Config supports encryption:
encrypt:
key: ${ENCRYPT_KEY} # Symmetric key for encryption/decryption
# Encrypted values in config files:
spring:
datasource:
password: '{cipher}AQA2J5...' # Encrypted
Configuration Best Practices
1. Property Naming Convention
# Use hierarchical structure
hiveops:
mgmt:
license:
offline-grace-period: 7
validation-interval: 24
auth:
mfa:
enabled: true
totp-digits: 6
2. Environment Separation
config-repo/
├── application.yml # Common to all
├── hiveops-mgmt-dev.yml # Dev-specific
├── hiveops-mgmt-staging.yml # Staging-specific
├── hiveops-mgmt-prod.yml # Prod-specific
3. Configuration Documentation
Add comments to config files:
# hiveops-auth.yml
# MFA Configuration
# totp-digits: Number of digits in TOTP code (6 or 8)
# totp-period: Time period in seconds (typically 30)
mfa:
totp-digits: 6
totp-period: 30
4. Git Workflow
- Feature branches: Create branch for config changes
- Pull requests: Require review before merging
- Version tags: Tag releases (v1.0.0, v1.1.0)
- Rollback: Easy to revert to previous commit
Last Updated: 2026-02-13