diff --git a/c4po.sh b/c4po.sh index d9b6bcd..37e44c0 100755 --- a/c4po.sh +++ b/c4po.sh @@ -1,15 +1,5 @@ #!/bin/bash baseDir=$(pwd) - -composeDir=$baseDir"/security-c4po-cfg" -keycloakVolume="security-c4po-cfg/volumes/keycloak/data/*" -mongoVolume="security-c4po-cfg/volumes/mongodb/data/*" - -composeKeycloak=$baseDir"/security-c4po-cfg/kc/docker-compose.keycloak.yml" -composeDatabase=$baseDir"/security-c4po-cfg/mongodb/docker-compose.mongodb.yml" -composeFrontend=$baseDir"/security-c4po-cfg/frontend/docker-compose.frontend.yml" -composeBackend=$baseDir"/security-c4po-cfg/backend/docker-compose.backend.yml" - compose=$baseDir"/security-c4po-cfg/docker-compose.yml" echo -e " @@ -24,24 +14,21 @@ ______| |______ |_____ |_____| | \_ __|__ | | _/_/_/ _/ echo "-------------CLEAN UP Container---------------" echo -e "\n" -rm -r ${keycloakVolume} docker rm -f c4po-keycloak -docker rm -f c4po-keycloak-postgres -docker rm -f c4po-db +#docker rm -f c4po-db ### toggle to clear database with every start ### docker rm -f c4po-api docker rm -f c4po-angular echo -e "\n" + echo "-----------------Start Build------------------" echo -e "\n" echo " - Backend: " -docker-compose -f ${composeBackend} build +docker-compose -f ${compose} build c4po-api echo -e "\n" echo " - Frontend: " -docker-compose -f ${composeFrontend} build +docker-compose -f ${compose} build c4po-angular echo -e "\n" -# docker-compose -f ${compose} up echo "------------Start Docker Container------------" echo -e "\n" -docker-compose -f ${composeKeycloak} -f ${composeDatabase} -f ${composeBackend} -f ${composeFrontend} up -# docker-compose -f ${compose} up +docker-compose -f ${compose} up diff --git a/security-c4po-angular/src/app/project-overview/project-overview.component.html b/security-c4po-angular/src/app/project-overview/project-overview.component.html index 42effdd..2cbcc18 100644 --- a/security-c4po-angular/src/app/project-overview/project-overview.component.html +++ b/security-c4po-angular/src/app/project-overview/project-overview.component.html @@ -66,7 +66,7 @@ -
+

{{'project.overview.no.projects' | translate}}

diff --git a/security-c4po-api/Dockerfile b/security-c4po-api/Dockerfile index 8c3ffcf..b5a2b79 100644 --- a/security-c4po-api/Dockerfile +++ b/security-c4po-api/Dockerfile @@ -6,15 +6,12 @@ RUN mkdir /data RUN chown security-c4po-api:security-c4po-api /data USER security-c4po-api -# GET CURRENT STAGE -ARG STAGE -ENV ENV_STAGE=$STAGE - # COPY PACKAGE INTO IMAGE COPY ./build/libs/security-c4po-api-0.0.1-SNAPSHOT.jar / USER security-c4po-api EXPOSE 8443 -# RUN JAVA +# WAIT FOR KEYCLOAK & RUN JAVA +COPY ./wait-for-keycloak.sh / # CMD [ "java", "-jar", "security-c4po-api-0.0.1-SNAPSHOT.jar" ] -ENTRYPOINT [ "java", "-jar", "-Dspring.profiles.active=${ENV_STAGE}", "security-c4po-api-0.0.1-SNAPSHOT.jar" ] +ENTRYPOINT [ "./wait-for-keycloak.sh", "http://c4po-keycloak:8080/auth/realms/c4po_realm_local", "java", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-jar", "security-c4po-api-0.0.1-SNAPSHOT.jar" ] diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/security/WebSecurityConfiguration.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/security/WebSecurityConfiguration.kt index 6bc3c51..6c49e2f 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/security/WebSecurityConfiguration.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/security/WebSecurityConfiguration.kt @@ -1,12 +1,20 @@ package com.securityc4po.api.configuration.security +import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile import org.springframework.http.HttpMethod import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity import org.springframework.security.config.web.server.ServerHttpSecurity +import org.springframework.security.oauth2.core.OAuth2TokenValidator +import org.springframework.security.oauth2.jwt.Jwt +import org.springframework.security.oauth2.jwt.JwtValidators +import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder +import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder +import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders import org.springframework.security.web.server.SecurityWebFilterChain import org.springframework.web.cors.CorsConfiguration @@ -16,6 +24,12 @@ import org.springframework.web.cors.CorsConfiguration @ComponentScan class WebSecurityConfiguration(private val userAccountDetailsService: UserAccountDetailsService) { + @Value("\${external.issuer-uri}") + var externalIssuerUri: String? = null + + @Value("\${spring.security.oauth2.resourceserver.jwt.issuer-uri}") + var internalIssuerUri: String? = null + @Bean fun setSecurityWebFilterChains(http: ServerHttpSecurity): SecurityWebFilterChain { http.cors().configurationSource { @@ -28,19 +42,19 @@ class WebSecurityConfiguration(private val userAccountDetailsService: UserAccoun this.addAllowedMethod(HttpMethod.PUT) } } - .and() - .csrf() - .disable() - .authorizeExchange() - .pathMatchers(HttpMethod.GET, "/v1/projects/**").authenticated() - .pathMatchers(HttpMethod.GET, "/v1/pentests/**").authenticated() - .pathMatchers("/actuator/**").permitAll() - .pathMatchers("/docs/SecurityC4PO.html").permitAll() - .anyExchange().authenticated() - .and() - .oauth2ResourceServer() - .jwt() - .jwtAuthenticationConverter(appuserJwtAuthenticationConverter()) + .and() + .csrf() + .disable() + .authorizeExchange() + .pathMatchers(HttpMethod.GET, "/v1/projects/**").authenticated() + .pathMatchers(HttpMethod.GET, "/v1/pentests/**").authenticated() + .pathMatchers("/actuator/**").permitAll() + .pathMatchers("/docs/SecurityC4PO.html").permitAll() + .anyExchange().authenticated() + .and() + .oauth2ResourceServer() + .jwt() + .jwtAuthenticationConverter(appuserJwtAuthenticationConverter()) return http.build() } @@ -48,4 +62,13 @@ class WebSecurityConfiguration(private val userAccountDetailsService: UserAccoun fun appuserJwtAuthenticationConverter(): AppuserJwtAuthConverter { return AppuserJwtAuthConverter(userAccountDetailsService) } + + @Bean + @Profile("COMPOSE") + fun jwtDecoder(): ReactiveJwtDecoder { + val jwtDecoder = ReactiveJwtDecoders.fromIssuerLocation(internalIssuerUri) as NimbusReactiveJwtDecoder + val withIssuer: OAuth2TokenValidator = JwtValidators.createDefaultWithIssuer(externalIssuerUri) + jwtDecoder.setJwtValidator(withIssuer) + return jwtDecoder + } } diff --git a/security-c4po-api/src/main/resources/application-COMPOSE.properties b/security-c4po-api/src/main/resources/application-COMPOSE.properties index 2b2f4cc..ba018d3 100644 --- a/security-c4po-api/src/main/resources/application-COMPOSE.properties +++ b/security-c4po-api/src/main/resources/application-COMPOSE.properties @@ -1,7 +1,7 @@ ## IdentityProvider (Keycloak) ## -spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8888/auth/realms/c4po_realm_local -keycloakhost=localhost -keycloak.client.url=http://localhost:8888 +spring.security.oauth2.resourceserver.jwt.issuer-uri=http://c4po-keycloak:8080/auth/realms/c4po_realm_local +keycloakhost=c4po-keycloak +keycloak.client.url=http://c4po-keycloak:8080 keycloak.client.realm.path=auth/realms/c4po_realm_local/ ## Database (MONGODB) Config ## diff --git a/security-c4po-api/src/main/resources/application.properties b/security-c4po-api/src/main/resources/application.properties index c98625e..f1ac14a 100644 --- a/security-c4po-api/src/main/resources/application.properties +++ b/security-c4po-api/src/main/resources/application.properties @@ -17,6 +17,7 @@ spring.data.mongodb.auto-index-creation=true ## IdentityProvider (Keycloak) ## spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/auth/realms/c4po_realm_local +external.issuer-uri=http://localhost:8080/auth/realms/c4po_realm_local keycloakhost=localhost keycloak.client.url=http://localhost:8080 keycloak.client.realm.path=auth/realms/c4po_realm_local/ diff --git a/security-c4po-api/wait-for-keycloak.sh b/security-c4po-api/wait-for-keycloak.sh new file mode 100755 index 0000000..11c112e --- /dev/null +++ b/security-c4po-api/wait-for-keycloak.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# wait-for-keycloak.sh + +set -e + +host="$1" +shift + +printf 'Waiting for keycloak...' +until $(curl --output /dev/null --silent --head --fail $host); do + printf '.' + sleep 4 +done + +printf '\nKeycloak is up and running - Starting C4PO API' + +exec "$@" \ No newline at end of file diff --git a/security-c4po-cfg/backend/docker-compose.backend.yml b/security-c4po-cfg/backend/docker-compose.backend.yml deleted file mode 100644 index 80bc233..0000000 --- a/security-c4po-cfg/backend/docker-compose.backend.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: '3.1' - -services: - c4po-api: - build: '../../security-c4po-api' - image: security-c4po-api:latest - container_name: c4po-api - environment: - - SPRING_PROFILES_ACTIVE=COMPOSE - deploy: - resources: - limits: - memory: "1G" - ports: - - 8443:8443 diff --git a/security-c4po-cfg/docker-compose.yml b/security-c4po-cfg/docker-compose.yml index c3935c3..844f367 100644 --- a/security-c4po-cfg/docker-compose.yml +++ b/security-c4po-cfg/docker-compose.yml @@ -1,10 +1,10 @@ version: '2' volumes: - c4po-keycloak-postgres: c4po-db: services: + # Database c4po-db: image: mongo:latest container_name: c4po-db @@ -39,7 +39,7 @@ services: deploy: resources: limits: - memory: "1G" + memory: "2G" ports: - 4200:4200 networks: @@ -56,7 +56,7 @@ services: deploy: resources: limits: - memory: "1G" + memory: "2G" ports: - 8443:8443 networks: diff --git a/security-c4po-cfg/frontend/docker-compose.frontend.yml b/security-c4po-cfg/frontend/docker-compose.frontend.yml deleted file mode 100644 index 4bdbf1f..0000000 --- a/security-c4po-cfg/frontend/docker-compose.frontend.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: '3.1' - -services: - c4po-angular: - build: '../../security-c4po-angular' - image: security-c4po-angular:latest - container_name: c4po-angular - deploy: - resources: - limits: - memory: "1G" - ports: - - 4200:4200 diff --git a/security-c4po-cfg/kc/docker-compose.keycloak.yml b/security-c4po-cfg/kc/docker-compose.keycloak.yml deleted file mode 100644 index 51204a1..0000000 --- a/security-c4po-cfg/kc/docker-compose.keycloak.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '3.1' - -services: - c4po-keycloak: - container_name: c4po-keycloak - image: jboss/keycloak:11.0.3 - volumes: - - ../cfg/c4po_realm_export.json:/tmp/c4po_realm_export.json - ports: - - 8888:8080 - env_file: - - ../cfg/keycloak.env - c4po-keycloak-postgress: - container_name: c4po-keycloak-postgres - image: postgres:10.16-alpine - env_file: - - ../cfg/keycloakdb.env - ports: - - 5433:5432 - volumes: - - ../volumes/keycloak/data:/var/lib/postgres/data diff --git a/security-c4po-cfg/mongodb/docker-compose.mongodb.yml b/security-c4po-cfg/mongodb/docker-compose.mongodb.yml deleted file mode 100644 index d6c959d..0000000 --- a/security-c4po-cfg/mongodb/docker-compose.mongodb.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: '3.1' - -services: - c4po-db: - image: mongo:4.4.6 - container_name: c4po-db - volumes: - - ../volumes/mongodb/data:/data/db - deploy: - resources: - limits: - memory: "1G" - ports: - - 27017:27017