diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..08c0845 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +CLOUDFLARE_ACCOUNT_ID="" +CLOUDFLARE_API_KEY="" +CLOUDFLARE_EMAIL="" +ENV="" \ No newline at end of file diff --git a/.gitea/workflows/prod_image_build_push.yaml b/.gitea/workflows/prod_image_build_push.yaml new file mode 100644 index 0000000..ec31a2c --- /dev/null +++ b/.gitea/workflows/prod_image_build_push.yaml @@ -0,0 +1,64 @@ +name: Promote image with tag test to prod +run-name: Build started by $ {{gitea.actor}} +on: + push: + branches: [main] +jobs: + tag: + runs-on: ubuntu-latest + outputs: + new_version: ${{ steps.new_version.outputs.new_version }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Get new version + id: new_version + run: | + VERSION=$(git describe --tags --abbrev=0) + echo ${VERSION} + MAJOR=$(echo ${VERSION} | cut -d "." -f 1) + MINOR=$(echo ${VERSION} | cut -d "." -f 2) + PATCH=0 + NEW_MINOR=$(( ${MINOR} + 1)) + echo ${NEW_MINOR} + echo "new_version=$(echo "${MAJOR}.${NEW_MINOR}.${PATCH}")" >> $GITHUB_OUTPUT + build_tag_push: + runs-on: ubuntu-latest + needs: tag + container: + image: catthehacker/ubuntu:act-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: JDK setup + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '17' + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v3 + - name: Create and push tag + run: | + echo "NEW_VERSION=${{ needs.tag.outputs.new_version }}" + git config --global user.name "${{gitea.actor}}" + git config --global user.email "${{ gitea.actor }}@users.noreply.github.com" + git tag -a ${{ needs.tag.outputs.new_version }} -m "Pushing new version ${{ needs.tag.outputs.new_version }}" + git push origin ${{ needs.tag.outputs.new_version }} + - name: Log in to Gitea Docker Registry + uses: docker/login-action@v3 + with: + registry: 'http://192.168.0.100:8928' + username: hitanshu + password: ${{ secrets.TOKEN }} + - name: Gradle build + run: ./gradlew bootBuildImage --imageName=192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} + - name: Tag image as test + run: docker tag 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} 192.168.0.100:8928/hithomelabs/cftunnels:prod + - name: Push to Gitea Registry + run: | + docker push 192.168.0.100:8928/hithomelabs/cftunnels:prod + docker push 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} diff --git a/.gitea/workflows/test_build.yml b/.gitea/workflows/test_build.yml new file mode 100644 index 0000000..ae070cd --- /dev/null +++ b/.gitea/workflows/test_build.yml @@ -0,0 +1,20 @@ +name: sample gradle build and test +run-name: Build started by $ {{gitea.actor}} +on: + pull_request: + branches: [test] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + - name: JDK setup + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '17' + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v3 + - name: Gradle build + run: ./gradlew build --info \ No newline at end of file diff --git a/.gitea/workflows/test_image_build_push.yml b/.gitea/workflows/test_image_build_push.yml new file mode 100644 index 0000000..f53e140 --- /dev/null +++ b/.gitea/workflows/test_image_build_push.yml @@ -0,0 +1,64 @@ +name: sample gradle build and test +run-name: Build started by $ {{gitea.actor}} +on: + push: + branches: [test] +jobs: + tag: + runs-on: ubuntu-latest + outputs: + new_version: ${{ steps.new_version.outputs.new_version }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Get new version + id: new_version + run: | + VERSION=$(git describe --tags --abbrev=0) + echo ${VERSION} + MAJOR=$(echo ${VERSION} | cut -d "." -f 1) + MINOR=$(echo ${VERSION} | cut -d "." -f 2) + PATCH=$(echo ${VERSION} | cut -d "." -f 3) + NEW_PATCH=$(( ${PATCH} + 1)) + echo ${NEW_PATCH} + echo "new_version=$(echo "${MAJOR}.${MINOR}.${NEW_PATCH}")" >> $GITHUB_OUTPUT + build_tag_push: + runs-on: ubuntu-latest + needs: tag + container: + image: catthehacker/ubuntu:act-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: JDK setup + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '17' + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v3 + - name: Create and push tag + run: | + echo "NEW_VERSION=${{ needs.tag.outputs.new_version }}" + git config --global user.name "${{gitea.actor}}" + git config --global user.email "${{ gitea.actor }}@users.noreply.github.com" + git tag -a ${{ needs.tag.outputs.new_version }} -m "Pushing new version ${{ needs.tag.outputs.new_version }}" + git push origin ${{ needs.tag.outputs.new_version }} + - name: Log in to Gitea Docker Registry + uses: docker/login-action@v3 + with: + registry: 'http://192.168.0.100:8928' + username: hitanshu + password: ${{ secrets.TOKEN }} + - name: Gradle build + run: ./gradlew bootBuildImage --imageName=192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} + - name: Tag image as test + run: docker tag 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} 192.168.0.100:8928/hithomelabs/cftunnels:test + - name: Push to Gitea Registry + run: | + docker push 192.168.0.100:8928/hithomelabs/cftunnels:test + docker push 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} diff --git a/CFTunnels/Get tunnels.bru b/CFTunnels/Get tunnels.bru index 14d6916..231ee08 100644 --- a/CFTunnels/Get tunnels.bru +++ b/CFTunnels/Get tunnels.bru @@ -5,7 +5,7 @@ meta { } get { - url: http://localhost8080/cloudflare/tunnels + url: {{base_url}}/cloudflare/tunnels body: none auth: none } diff --git a/CFTunnels/Tunnel.bru b/CFTunnels/Tunnel.bru index 2944af1..826b583 100644 --- a/CFTunnels/Tunnel.bru +++ b/CFTunnels/Tunnel.bru @@ -5,7 +5,7 @@ meta { } get { - url: http://localhost:8080/cloudflare/tunnel/{{tunnel_id}} + url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}} body: none auth: none } diff --git a/CFTunnels/Write ingress.bru b/CFTunnels/Write ingress.bru index 343a4c4..9930a0b 100644 --- a/CFTunnels/Write ingress.bru +++ b/CFTunnels/Write ingress.bru @@ -4,8 +4,16 @@ meta { seq: 2 } -post { - url: http://localhost:8080/cloudflare/tunnel/50df9101-f625-4618-b7c5-100338a57124 - body: none +put { + url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}}/add + body: json auth: none } + +body:json { + { + "service": "http://192.168.0.100:3457", + "hostname": "random.hithomelabs.com", + "originRequest": {} + } +} diff --git a/CFTunnels/delete mapping.bru b/CFTunnels/delete mapping.bru index 3afa061..c9e3dbb 100644 --- a/CFTunnels/delete mapping.bru +++ b/CFTunnels/delete mapping.bru @@ -5,7 +5,15 @@ meta { } put { - url: http://localhost:8080/cloudflare/tunnel/50df9101-f625-4618-b7c5-100338a57124/add - body: none + url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}}/delete + body: json auth: none } + +body:json { + { + "service": "http://192.168.0.100:6000", + "hostname": "random.hithomelabs.com", + "originRequest": {} + } +} diff --git a/CFTunnels/environments/CFTunnels Local.bru b/CFTunnels/environments/CFTunnels Local.bru new file mode 100644 index 0000000..6d2b6b0 --- /dev/null +++ b/CFTunnels/environments/CFTunnels Local.bru @@ -0,0 +1,4 @@ +vars { + tunnel_id: 50df9101-f625-4618-b7c5-100338a57124 + base_url: http://localhost:8080 +} diff --git a/CFTunnels/environments/CFTunnels.bru b/CFTunnels/environments/CFTunnels.bru index fdb44d8..d8219ab 100644 --- a/CFTunnels/environments/CFTunnels.bru +++ b/CFTunnels/environments/CFTunnels.bru @@ -1,3 +1,4 @@ vars { tunnel_id: 50df9101-f625-4618-b7c5-100338a57124 + base_url: https://testcf.hithomelabs.com } diff --git a/build.gradle b/build.gradle index 663b328..bfc0540 100644 --- a/build.gradle +++ b/build.gradle @@ -13,12 +13,17 @@ java { } } +test { + systemProperty 'spring.profiles.active', 'test' +} + repositories { mavenCentral() } dependencies { - implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.0.3' + implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.8.5' + implementation group: 'org.springframework.boot', name:'spring-boot-starter-oauth2-client', version: '3.5.5' implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..7cac007 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,14 @@ +services: + app: + image: gitea.hithomelabs.com/hithomelabs/cftunnels:${ENV} + container_name: cftunnels_${ENV} + environment: + - CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID} + - CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY} + - CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL} + - ENV=${ENV} + - OAUTH_CLIENT_ID=${OAUTH_CLIENT_ID} + - OAUTH_CLIENT_SECRET=${OAUTH_CLIENT_SECRET} + ports: + - 5002:8080 + restart: unless-stopped \ No newline at end of file diff --git a/src/main/java/com/hithomelabs/CFTunnels/Config/AuthoritiesToGroupMapping.java b/src/main/java/com/hithomelabs/CFTunnels/Config/AuthoritiesToGroupMapping.java new file mode 100644 index 0000000..b323700 --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Config/AuthoritiesToGroupMapping.java @@ -0,0 +1,28 @@ +package com.hithomelabs.CFTunnels.Config; + +import com.hithomelabs.CFTunnels.Models.Authorities; +import com.hithomelabs.CFTunnels.Models.Groups; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@Configuration +public class AuthoritiesToGroupMapping { + + public Map> getAuthorityForGroup(){ + HashMap> mappings = new HashMap<>(); + mappings.put(Groups.GITEA_USER, new HashSet<>(Set.of(new SimpleGrantedAuthority(Authorities.ROLE_USER)))); + mappings.put(Groups.POWER_USER, new HashSet<>(Set.of(new SimpleGrantedAuthority(Authorities.ROLE_USER)))); + mappings.put(Groups.HOMELAB_DEVELOPER, new HashSet<>(Set.of(new SimpleGrantedAuthority(Authorities.ROLE_DEVELOPER)))); + mappings.put(Groups.SYSTEM_ADMIN, new HashSet<>(Set.of(new SimpleGrantedAuthority(Authorities.ROLE_APPROVER), new SimpleGrantedAuthority(Authorities.ROLE_ADMIN)))); + return mappings; + } + + + +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Config/CustomOidcUserConfiguration.java b/src/main/java/com/hithomelabs/CFTunnels/Config/CustomOidcUserConfiguration.java new file mode 100644 index 0000000..22a4e64 --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Config/CustomOidcUserConfiguration.java @@ -0,0 +1,45 @@ +package com.hithomelabs.CFTunnels.Config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Configuration +public class CustomOidcUserConfiguration extends OidcUserService { + + @Autowired + AuthoritiesToGroupMapping authoritiesToGroupMapping; + + @Override + public OidcUser loadUser(OidcUserRequest userRequest) { + // * * Delegate to the default implementation for loading user and claims + OidcUser oidcUser = super.loadUser(userRequest); + + // * * Copy existing authorities (e.g. scopes → authorities) + Set mappedAuthorities = new HashSet<>(); + + // * * Extract your custom claim (change "roles" to your claim name) + List groups = oidcUser.getClaimAsStringList("groups"); + if (groups != null) { + groups.forEach(group -> + mappedAuthorities.addAll(authoritiesToGroupMapping.getAuthorityForGroup().get(group)) + ); + } + + // * * Return a new DefaultOidcUser with merged authorities + return new DefaultOidcUser( + mappedAuthorities, + oidcUser.getIdToken(), + oidcUser.getUserInfo() + ); + } + } + diff --git a/src/main/java/com/hithomelabs/CFTunnels/Config/OpenApiConfig.java b/src/main/java/com/hithomelabs/CFTunnels/Config/OpenApiConfig.java new file mode 100644 index 0000000..ef3b098 --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Config/OpenApiConfig.java @@ -0,0 +1,26 @@ +package com.hithomelabs.CFTunnels.Config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; + +@Configuration +public class OpenApiConfig { + + @Value("${api.corsResolveUrl}") + private String corsResolveUrl; + + @Bean + public OpenAPI openAPI(){ + Server httpsServer = new Server().url(corsResolveUrl); + OpenAPI openApi = new OpenAPI(); + ArrayList servers = new ArrayList<>(); + servers.add(httpsServer); + openApi.setServers(servers); + return openApi; + } +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Config/Security/SecuirtyConfig.java b/src/main/java/com/hithomelabs/CFTunnels/Config/Security/SecuirtyConfig.java new file mode 100644 index 0000000..7bd9c1e --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Config/Security/SecuirtyConfig.java @@ -0,0 +1,39 @@ +package com.hithomelabs.CFTunnels.Config.Security; + +import com.hithomelabs.CFTunnels.Config.CustomOidcUserConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer; +import org.springframework.security.web.SecurityFilterChain; + + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity( + prePostEnabled = true, + securedEnabled = true, + jsr250Enabled = true +) +public class SecuirtyConfig { + + @Autowired + private CustomOidcUserConfiguration customOidcUserConfiguration; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(auth -> auth + .anyRequest().authenticated() + ) + .with(new OAuth2LoginConfigurer<>(), oauth2 -> oauth2.userInfoEndpoint(u -> u.oidcUserService(customOidcUserConfiguration))); + + + return http.build(); + } + +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Controllers/HomeController.java b/src/main/java/com/hithomelabs/CFTunnels/Controllers/HomeController.java new file mode 100644 index 0000000..43ea57a --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Controllers/HomeController.java @@ -0,0 +1,32 @@ +package com.hithomelabs.CFTunnels.Controllers; + + +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class HomeController implements ErrorController { + + private static final String ERROR_PATH = "/error"; + + /** + * Redirects the root (including any query params like ?continue=…) + * straight into Swagger UI. + */ + @GetMapping("/") + public String rootRedirect() { + return "redirect:/swagger-ui/index.html"; + } + + /** + * Catches any errors (404s, unhandled paths) and punts them + * into the same Swagger UI page. + */ + @RequestMapping(ERROR_PATH) + public String onError() { + return "redirect:/swagger-ui/index.html"; + } + +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Controllers/TunnelController.java b/src/main/java/com/hithomelabs/CFTunnels/Controllers/TunnelController.java index 9e8ad9c..612fc78 100644 --- a/src/main/java/com/hithomelabs/CFTunnels/Controllers/TunnelController.java +++ b/src/main/java/com/hithomelabs/CFTunnels/Controllers/TunnelController.java @@ -1,8 +1,7 @@ package com.hithomelabs.CFTunnels.Controllers; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; +import com.hithomelabs.CFTunnels.Config.AuthoritiesToGroupMapping; import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.CFTunnels.Config.RestTemplateConfig; import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; @@ -10,8 +9,12 @@ import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.CFTunnels.Models.TunnelResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.http.*; -import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; @@ -21,10 +24,13 @@ import java.util.Map; @RestController @RequestMapping("/cloudflare") -public class TunnelController { +public class TunnelController implements ErrorController { private final RestTemplate restTemplate = new RestTemplate(); + private static final String ERROR_PATH = "/error"; + @Autowired + private AuthoritiesToGroupMapping authoritiesToGroupMapping; @Autowired private CloudflareConfig cloudflareConfig; @@ -34,6 +40,20 @@ public class TunnelController { @Autowired private RestTemplateConfig restTemplateConfig; + @PreAuthorize("hasAnyRole('USER')") + @GetMapping("/whoami") + public Map whoAmI(@AuthenticationPrincipal OidcUser oidcUser) { + + List authorities = oidcUser.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .toList(); + return Map.of( + "username", oidcUser.getPreferredUsername(), + "roles", authorities + ); + } + + @PreAuthorize("hasAnyRole('USER')") @GetMapping("/tunnels") public ResponseEntity> getTunnels(){ @@ -50,6 +70,7 @@ public class TunnelController { return ResponseEntity.ok(jsonResponse); } + @PreAuthorize("hasAnyRole('DEVELOPER')") @GetMapping("/tunnel/{tunnelId}") public ResponseEntity> getTunnelConfigurations(@PathVariable String tunnelId) throws JsonProcessingException { @@ -67,6 +88,7 @@ public class TunnelController { } // 50df9101-f625-4618-b7c5-100338a57124 + @PreAuthorize("hasAnyRole('ADMIN')") @PutMapping("/tunnel/{tunnelId}/add") public ResponseEntity> addTunnelconfiguration(@PathVariable String tunnelId, @RequestBody Ingress ingress) throws JsonProcessingException { @@ -95,6 +117,7 @@ public class TunnelController { return ResponseEntity.ok(jsonResponse); } + @PreAuthorize("hasAnyRole('DEVELOPER')") @PutMapping("/tunnel/{tunnelId}/delete") public ResponseEntity> deleteTunnelConfiguration(@PathVariable String tunnelId, @RequestBody Ingress ingress) throws JsonProcessingException { diff --git a/src/main/java/com/hithomelabs/CFTunnels/Models/Authorities.java b/src/main/java/com/hithomelabs/CFTunnels/Models/Authorities.java new file mode 100644 index 0000000..f26a17b --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Models/Authorities.java @@ -0,0 +1,10 @@ +package com.hithomelabs.CFTunnels.Models; + +public class Authorities { + + public static final String ROLE_ADMIN = "ROLE_ADMIN"; + public static final String ROLE_DEVELOPER = "ROLE_DEVELOPER"; + public static final String ROLE_USER = "ROLE_USER"; + public static final String ROLE_APPROVER = "ROLE_APPROVER"; + +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Models/Groups.java b/src/main/java/com/hithomelabs/CFTunnels/Models/Groups.java new file mode 100644 index 0000000..f7c213d --- /dev/null +++ b/src/main/java/com/hithomelabs/CFTunnels/Models/Groups.java @@ -0,0 +1,10 @@ +package com.hithomelabs.CFTunnels.Models; + +public class Groups { + + public static final String HOMELAB_DEVELOPER = "homelab developer"; + public static final String SYSTEM_ADMIN = "authentik Admins"; + public static final String POWER_USER = "arr premium"; + public static final String GITEA_USER = "gitrestricted"; + +} diff --git a/src/main/java/com/hithomelabs/CFTunnels/Models/Ingress.java b/src/main/java/com/hithomelabs/CFTunnels/Models/Ingress.java index 8adcc89..7c6c7be 100644 --- a/src/main/java/com/hithomelabs/CFTunnels/Models/Ingress.java +++ b/src/main/java/com/hithomelabs/CFTunnels/Models/Ingress.java @@ -8,6 +8,16 @@ public class Ingress { private String service; private String hostname; private Map originRequest; + private String path; + + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } public static boolean deleteByHostName(List ingressList, String toBeDeleted){ return ingressList.removeIf(ingress -> ingress.getHostname() != null && ingress.getHostname().equals(toBeDeleted)); diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties new file mode 100644 index 0000000..9001ed2 --- /dev/null +++ b/src/main/resources/application-local.properties @@ -0,0 +1 @@ +api.corsResolveUrl=http://localhost:8080 \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..5126249 --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1 @@ +api.corsResolveUrl=https://cftunnels.hithomelabs.com \ No newline at end of file diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties new file mode 100644 index 0000000..1ea328b --- /dev/null +++ b/src/main/resources/application-test.properties @@ -0,0 +1 @@ +api.corsResolveUrl=https://testcf.hithomelabs.com \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2c265e1..4774989 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,3 +2,18 @@ spring.application.name=CFTunnels cloudflare.accountId=${CLOUDFLARE_ACCOUNT_ID} cloudflare.apiKey=${CLOUDFLARE_API_KEY} cloudflare.email=${CLOUDFLARE_EMAIL} +spring.profiles.active=${ENV} + +/ * * Masking sure app works behind a reverse proxy +server.forward-headers-strategy=framework + +spring.security.oauth2.client.registration.cftunnels.client-id=${OAUTH_CLIENT_ID} +spring.security.oauth2.client.registration.cftunnels.client-secret=${OAUTH_CLIENT_SECRET} +spring.security.oauth2.client.registration.cftunnels.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.cftunnels.redirect-uri={baseUrl}/login/oauth2/code/cftunnels +spring.security.oauth2.client.registration.cftunnels.scope=openid,profile,email,offline_access,cftunnels +spring.security.oauth2.client.provider.cftunnels.authorization-uri=https://auth.hithomelabs.com/application/o/authorize/ +spring.security.oauth2.client.provider.cftunnels.token-uri=https://auth.hithomelabs.com/application/o/token/ +spring.security.oauth2.client.provider.cftunnels.user-info-uri=https://auth.hithomelabs.com/application/o/userinfo/ +spring.security.oauth2.client.provider.cftunnels.jwk-set-uri=https://auth.hithomelabs.com/application/o/cftunnels/jwks/ +spring.security.oauth2.client.provider.cftunnels.issuer-uri=https://auth.hithomelabs.com/application/o/cftunnels/ \ No newline at end of file