Migrate config to cameleer.saas.* naming convention
Move all SaaS configuration properties under the cameleer.saas.* namespace with all-lowercase dot-separated names and mechanical env var mapping. Aligns with the server (cameleer.server.*) and agent (cameleer.agent.*) conventions. Changes: - Move cameleer.identity.* → cameleer.saas.identity.* - Move cameleer.provisioning.* → cameleer.saas.provisioning.* - Move cameleer.certs.* → cameleer.saas.certs.* - Rename kebab-case properties to concatenated lowercase - Update all env vars to CAMELEER_SAAS_* mechanical mapping - Update DockerTenantProvisioner to pass CAMELEER_SERVER_* env vars to provisioned server containers (matching server's new convention) - Spring JWT config now derives from SaaS properties via cross-reference - Clean up orphaned properties in application-local.yml - Update docker-compose.yml, docker-compose.dev.yml, .env.example - Update CLAUDE.md, HOWTO.md, architecture.md, user-manual.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,10 +18,10 @@ public class PublicConfigController {
|
||||
private static final Logger log = LoggerFactory.getLogger(PublicConfigController.class);
|
||||
private static final String BOOTSTRAP_FILE = "/data/bootstrap/logto-bootstrap.json";
|
||||
|
||||
@Value("${cameleer.identity.logto-public-endpoint:${cameleer.identity.logto-endpoint:}}")
|
||||
@Value("${cameleer.saas.identity.logtopublicendpoint:${cameleer.saas.identity.logtoendpoint:}}")
|
||||
private String logtoPublicEndpoint;
|
||||
|
||||
@Value("${cameleer.identity.spa-client-id:}")
|
||||
@Value("${cameleer.saas.identity.spaclientid:}")
|
||||
private String spaClientId;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@@ -80,7 +80,7 @@ public class SecurityConfig {
|
||||
public JwtDecoder jwtDecoder(
|
||||
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") String jwkSetUri,
|
||||
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri:}") String issuerUri,
|
||||
@Value("${cameleer.identity.audience:}") String audience) throws Exception {
|
||||
@Value("${cameleer.saas.identity.audience:}") String audience) throws Exception {
|
||||
var jwkSource = JWKSourceBuilder.create(new URL(jwkSetUri)).build();
|
||||
var keySelector = new JWSVerificationKeySelector<SecurityContext>(
|
||||
JWSAlgorithm.ES384, jwkSource);
|
||||
|
||||
@@ -16,16 +16,16 @@ public class LogtoConfig {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogtoConfig.class);
|
||||
private static final String BOOTSTRAP_FILE = "/data/bootstrap/logto-bootstrap.json";
|
||||
|
||||
@Value("${cameleer.identity.logto-endpoint:}")
|
||||
@Value("${cameleer.saas.identity.logtoendpoint:}")
|
||||
private String logtoEndpoint;
|
||||
|
||||
@Value("${cameleer.identity.m2m-client-id:}")
|
||||
@Value("${cameleer.saas.identity.m2mclientid:}")
|
||||
private String m2mClientId;
|
||||
|
||||
@Value("${cameleer.identity.m2m-client-secret:}")
|
||||
@Value("${cameleer.saas.identity.m2mclientsecret:}")
|
||||
private String m2mClientSecret;
|
||||
|
||||
@Value("${cameleer.identity.server-endpoint:http://cameleer3-server:8081}")
|
||||
@Value("${cameleer.saas.identity.serverendpoint:http://cameleer3-server:8081}")
|
||||
private String serverEndpoint;
|
||||
|
||||
private String tradAppId;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class CertificateManagerAutoConfig {
|
||||
|
||||
@Bean
|
||||
CertificateManager certificateManager(
|
||||
@Value("${cameleer.certs.path:/certs}") String certsPath) {
|
||||
@Value("${cameleer.saas.certs.path:/certs}") String certsPath) {
|
||||
Path path = Path.of(certsPath);
|
||||
if (Files.isDirectory(path)) {
|
||||
log.info("Certs directory found at {} — enabling Docker certificate manager", certsPath);
|
||||
|
||||
@@ -195,27 +195,27 @@ public class DockerTenantProvisioner implements TenantProvisioner {
|
||||
"SPRING_DATASOURCE_URL=" + props.datasourceUrl(),
|
||||
"SPRING_DATASOURCE_USERNAME=cameleer",
|
||||
"SPRING_DATASOURCE_PASSWORD=cameleer_dev",
|
||||
"CLICKHOUSE_URL=jdbc:clickhouse://clickhouse:8123/cameleer",
|
||||
"CAMELEER_TENANT_ID=" + slug,
|
||||
"CAMELEER_AUTH_TOKEN=" + req.licenseToken(),
|
||||
"CAMELEER_JWT_SECRET=cameleer-dev-jwt-secret-change-in-production",
|
||||
"CAMELEER_OIDC_ISSUER_URI=" + props.oidcIssuerUri(),
|
||||
"CAMELEER_OIDC_JWK_SET_URI=" + props.oidcJwkSetUri(),
|
||||
"CAMELEER_OIDC_AUDIENCE=https://api.cameleer.local",
|
||||
"CAMELEER_CORS_ALLOWED_ORIGINS=" + props.corsOrigins(),
|
||||
"CAMELEER_LICENSE_TOKEN=" + req.licenseToken(),
|
||||
"CAMELEER_RUNTIME_ENABLED=true",
|
||||
"CAMELEER_SERVER_URL=http://" + name + ":8081",
|
||||
"CAMELEER_ROUTING_DOMAIN=" + props.publicHost(),
|
||||
"CAMELEER_ROUTING_MODE=path",
|
||||
"CAMELEER_JAR_STORAGE_PATH=/data/jars",
|
||||
"CAMELEER_SERVER_CLICKHOUSE_URL=jdbc:clickhouse://clickhouse:8123/cameleer",
|
||||
"CAMELEER_SERVER_TENANT_ID=" + slug,
|
||||
"CAMELEER_SERVER_SECURITY_BOOTSTRAPTOKEN=" + req.licenseToken(),
|
||||
"CAMELEER_SERVER_SECURITY_JWTSECRET=cameleer-dev-jwt-secret-change-in-production",
|
||||
"CAMELEER_SERVER_SECURITY_OIDCISSUERURI=" + props.oidcIssuerUri(),
|
||||
"CAMELEER_SERVER_SECURITY_OIDCJWKSETURI=" + props.oidcJwkSetUri(),
|
||||
"CAMELEER_SERVER_SECURITY_OIDCAUDIENCE=https://api.cameleer.local",
|
||||
"CAMELEER_SERVER_SECURITY_CORSALLOWEDORIGINS=" + props.corsOrigins(),
|
||||
"CAMELEER_SERVER_LICENSE_TOKEN=" + req.licenseToken(),
|
||||
"CAMELEER_SERVER_RUNTIME_ENABLED=true",
|
||||
"CAMELEER_SERVER_RUNTIME_SERVERURL=http://" + name + ":8081",
|
||||
"CAMELEER_SERVER_RUNTIME_ROUTINGDOMAIN=" + props.publicHost(),
|
||||
"CAMELEER_SERVER_RUNTIME_ROUTINGMODE=path",
|
||||
"CAMELEER_SERVER_RUNTIME_JARSTORAGEPATH=/data/jars",
|
||||
// Apps deployed by this server join the tenant network (isolated)
|
||||
"CAMELEER_DOCKER_NETWORK=" + tenantNetwork,
|
||||
"CAMELEER_JAR_DOCKER_VOLUME=cameleer-jars-" + slug
|
||||
"CAMELEER_SERVER_RUNTIME_DOCKERNETWORK=" + tenantNetwork,
|
||||
"CAMELEER_SERVER_RUNTIME_JARDOCKERVOLUME=cameleer-jars-" + slug
|
||||
));
|
||||
// If no CA bundle exists, fall back to TLS skip for OIDC (self-signed dev)
|
||||
if (!java.nio.file.Files.exists(java.nio.file.Path.of("/certs/ca.pem"))) {
|
||||
env.add("CAMELEER_OIDC_TLS_SKIP_VERIFY=true");
|
||||
env.add("CAMELEER_SERVER_SECURITY_OIDCTLSSKIPVERIFY=true");
|
||||
}
|
||||
|
||||
// Primary network = tenant-isolated network
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.siegeln.cameleer.saas.provisioning;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "cameleer.provisioning")
|
||||
@ConfigurationProperties(prefix = "cameleer.saas.provisioning")
|
||||
public record ProvisioningProperties(
|
||||
String serverImage,
|
||||
String serverUiImage,
|
||||
|
||||
@@ -17,7 +17,9 @@ spring:
|
||||
jwk-set-uri: http://localhost:3001/oidc/jwks
|
||||
|
||||
cameleer:
|
||||
clickhouse:
|
||||
url: jdbc:clickhouse://localhost:8123/cameleer
|
||||
runtime:
|
||||
cameleer3-server-endpoint: http://localhost:8081
|
||||
saas:
|
||||
identity:
|
||||
logtoendpoint: http://localhost:3001
|
||||
serverendpoint: http://localhost:8081
|
||||
provisioning:
|
||||
clickhouseurl: jdbc:clickhouse://localhost:8123/cameleer
|
||||
|
||||
@@ -20,8 +20,8 @@ spring:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
issuer-uri: ${LOGTO_ISSUER_URI:}
|
||||
jwk-set-uri: ${LOGTO_JWK_SET_URI:}
|
||||
issuer-uri: ${cameleer.saas.provisioning.publicprotocol:https}://${cameleer.saas.provisioning.publichost:localhost}/oidc
|
||||
jwk-set-uri: ${cameleer.saas.identity.logtoendpoint:http://logto:3001}/oidc/jwks
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
@@ -33,23 +33,26 @@ management:
|
||||
show-details: when-authorized
|
||||
|
||||
cameleer:
|
||||
identity:
|
||||
logto-endpoint: ${LOGTO_ENDPOINT:}
|
||||
logto-public-endpoint: ${LOGTO_PUBLIC_ENDPOINT:}
|
||||
m2m-client-id: ${LOGTO_M2M_CLIENT_ID:}
|
||||
m2m-client-secret: ${LOGTO_M2M_CLIENT_SECRET:}
|
||||
spa-client-id: ${LOGTO_SPA_CLIENT_ID:}
|
||||
audience: ${CAMELEER_OIDC_AUDIENCE:https://api.cameleer.local}
|
||||
server-endpoint: ${CAMELEER3_SERVER_ENDPOINT:http://cameleer3-server:8081}
|
||||
provisioning:
|
||||
server-image: ${CAMELEER_SERVER_IMAGE:gitea.siegeln.net/cameleer/cameleer3-server:latest}
|
||||
server-ui-image: ${CAMELEER_SERVER_UI_IMAGE:gitea.siegeln.net/cameleer/cameleer3-server-ui:latest}
|
||||
network-name: ${CAMELEER_NETWORK:cameleer-saas_cameleer}
|
||||
traefik-network: ${CAMELEER_TRAEFIK_NETWORK:cameleer-traefik}
|
||||
public-host: ${PUBLIC_HOST:localhost}
|
||||
public-protocol: ${PUBLIC_PROTOCOL:https}
|
||||
datasource-url: ${CAMELEER_SERVER_DB_URL:jdbc:postgresql://postgres:5432/cameleer3}
|
||||
clickhouse-url: ${CLICKHOUSE_URL:jdbc:clickhouse://clickhouse:8123/cameleer}
|
||||
oidc-issuer-uri: ${PUBLIC_PROTOCOL:https}://${PUBLIC_HOST:localhost}/oidc
|
||||
oidc-jwk-set-uri: http://logto:3001/oidc/jwks
|
||||
cors-origins: ${PUBLIC_PROTOCOL:https}://${PUBLIC_HOST:localhost}
|
||||
saas:
|
||||
identity:
|
||||
logtoendpoint: ${CAMELEER_SAAS_IDENTITY_LOGTOENDPOINT:}
|
||||
logtopublicendpoint: ${CAMELEER_SAAS_IDENTITY_LOGTOPUBLICENDPOINT:}
|
||||
m2mclientid: ${CAMELEER_SAAS_IDENTITY_M2MCLIENTID:}
|
||||
m2mclientsecret: ${CAMELEER_SAAS_IDENTITY_M2MCLIENTSECRET:}
|
||||
spaclientid: ${CAMELEER_SAAS_IDENTITY_SPACLIENTID:}
|
||||
audience: ${CAMELEER_SAAS_IDENTITY_AUDIENCE:https://api.cameleer.local}
|
||||
serverendpoint: ${CAMELEER_SAAS_IDENTITY_SERVERENDPOINT:http://cameleer3-server:8081}
|
||||
provisioning:
|
||||
serverimage: ${CAMELEER_SAAS_PROVISIONING_SERVERIMAGE:gitea.siegeln.net/cameleer/cameleer3-server:latest}
|
||||
serveruiimage: ${CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE:gitea.siegeln.net/cameleer/cameleer3-server-ui:latest}
|
||||
networkname: ${CAMELEER_SAAS_PROVISIONING_NETWORKNAME:cameleer-saas_cameleer}
|
||||
traefiknetwork: ${CAMELEER_SAAS_PROVISIONING_TRAEFIKNETWORK:cameleer-traefik}
|
||||
publichost: ${CAMELEER_SAAS_PROVISIONING_PUBLICHOST:localhost}
|
||||
publicprotocol: ${CAMELEER_SAAS_PROVISIONING_PUBLICPROTOCOL:https}
|
||||
datasourceurl: ${CAMELEER_SAAS_PROVISIONING_DATASOURCEURL:jdbc:postgresql://postgres:5432/cameleer3}
|
||||
clickhouseurl: ${CAMELEER_SAAS_PROVISIONING_CLICKHOUSEURL:jdbc:clickhouse://clickhouse:8123/cameleer}
|
||||
oidcissueruri: ${cameleer.saas.provisioning.publicprotocol}://${cameleer.saas.provisioning.publichost}/oidc
|
||||
oidcjwkseturi: http://logto:3001/oidc/jwks
|
||||
corsorigins: ${cameleer.saas.provisioning.publicprotocol}://${cameleer.saas.provisioning.publichost}
|
||||
certs:
|
||||
path: ${CAMELEER_SAAS_CERTS_PATH:/certs}
|
||||
|
||||
Reference in New Issue
Block a user