diff --git a/deploy/configmap.yml b/deploy/configmap.yml new file mode 100644 index 0000000..52632c6 --- /dev/null +++ b/deploy/configmap.yml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: onboarding +data: + io.insee.dev.k8sonboarding.clusterName: "" + io.insee.dev.k8sonboarding.insecure: "" + io.insee.dev.k8sonboarding.apiserver-url: "" + io.insee.dev.k8sonboarding.user-prefix: "" + io.insee.dev.k8sonboarding.group-prefix: "" + io.insee.dev.k8sonboarding.namespace-prefix: "" + io.insee.dev.k8sonboarding.namespace-group-prefix: "" + io.insee.dev.k8sonboarding.name-namespace-admin: "" + io.insee.dev.k8sonboarding.jwt.username-claim: "" + spring.security.oauth2.resourceserver.jwt.issuer-uri: "" + spring.security.oauth2.resourceserver.jwt.jwk-set-uri: "" + io.insee.dev.k8sonboarding.ui.clientId: "" + io.insee.dev.k8sonboarding.ui.authority: "" + io.insee.dev.k8sonboarding.ui.groupFilter: "" + io.insee.dev.k8sonboarding.ui.user-namespace-enabled: "" + io.insee.dev.k8sonboarding.ui.namespace-creation-allowed: "" + io.insee.dev.k8sonboarding.namespace-quota.memoryRequests: "" + io.insee.dev.k8sonboarding.namespace-quota.cpuRequests: "" + io.insee.dev.k8sonboarding.namespace-quota.memoryLimits: "" + io.insee.dev.k8sonboarding.namespace-quota.cpuLimits: "" + io.insee.dev.k8sonboarding.namespace-quota.storageRequests: "" + io.insee.dev.k8sonboarding.namespace-quota.storageLimits: "" + io.insee.dev.k8sonboarding.namespace-quota.podsCount: "" + io.insee.dev.k8sonboarding.does-remove-suffix: "" diff --git a/deploy/deployment.yml b/deploy/deployment.yml index b196bcb..84b4234 100644 --- a/deploy/deployment.yml +++ b/deploy/deployment.yml @@ -3,7 +3,7 @@ kind: Deployment metadata: name: onboarding spec: - replicas: 2 + replicas: 1 selector: matchLabels: app: onboarding @@ -15,3 +15,13 @@ spec: containers: - name: onboarding image: inseefrlab/k8s-onboarding:alpha + envFrom: + - configMapRef: + name: onboarding + resources: + limits: + cpu: "1" + memory: 4Gi + requests: + cpu: "0.5" + memory: 1Gi diff --git a/deploy/ingress.yml b/deploy/ingress.yml index d98348b..ed52e91 100644 --- a/deploy/ingress.yml +++ b/deploy/ingress.yml @@ -1,18 +1,18 @@ -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: onboarding - annotations: - kubernetes.io/ingress.class: nginx + labels: + name: onboarding spec: - tls: - - hosts: - - onboarding.example.com rules: - host: onboarding.example.com http: paths: - - path: / + - pathType: Prefix + path: "/" backend: - serviceName: onboarding - servicePort: http + service: + name: onboarding + port: + name: http diff --git a/pom.xml b/pom.xml index af329b5..d6b3cf6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,12 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot spring-boot-starter-parent - 2.7.4 + 3.2.2 @@ -45,12 +46,12 @@ io.fabric8 kubernetes-client - 6.1.1 + 6.10.0 io.fabric8 kubernetes-server-mock - 6.1.1 + 6.10.0 test @@ -62,40 +63,30 @@ org.springdoc springdoc-openapi-ui - 1.6.11 + 1.7.0 org.springframework.boot spring-boot-starter-oauth2-resource-server - - - org.springframework.security.oauth - spring-security-oauth2 - 2.5.2.RELEASE - - - - org.springframework.boot spring-boot-maven-plugin - com.github.eirslett frontend-maven-plugin - 1.12.1 + 1.15.0 ui target - v1.22.19 - v16.17.0 + v1.22.21 + v20.11.0 @@ -135,7 +126,7 @@ - + @@ -148,4 +139,4 @@ - + \ No newline at end of file diff --git a/src/main/java/io/insee/dev/k8sonboarding/configuration/UserProviderConfiguration.java b/src/main/java/io/insee/dev/k8sonboarding/configuration/UserProviderConfiguration.java index f94e08b..ae0e8dd 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/configuration/UserProviderConfiguration.java +++ b/src/main/java/io/insee/dev/k8sonboarding/configuration/UserProviderConfiguration.java @@ -1,8 +1,13 @@ package io.insee.dev.k8sonboarding.configuration; -import org.springframework.beans.factory.annotation.Value; +import java.util.List; +import java.util.stream.Collectors; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.jwt.Jwt; import io.insee.dev.k8sonboarding.configuration.security.UserProvider; @@ -11,20 +16,18 @@ @Configuration public class UserProviderConfiguration { - @Value("${io.insee.dev.k8sonboarding.jwt.username-claim}") - private String usernameClaim; - - @Value("${io.insee.dev.k8sonboarding.jwt.groups-claim:groups}") - private String groupsClaim; - @Bean public UserProvider getUserProvider() { return auth -> { final User user = new User(); - final Jwt jwt = (Jwt) auth.getPrincipal(); - user.setId(jwt.getClaimAsString(usernameClaim)); - user.setGroups(jwt.getClaimAsStringList(groupsClaim)); - user.setAuthToken(jwt.getTokenValue()); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + user.setId(authentication.getPrincipal().toString()); + List roles = authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .map(role -> role.replace("ROLE_", "")) + .collect(Collectors.toList()); + user.setGroups(roles); + user.setAuthToken(((Jwt) auth.getPrincipal()).getTokenValue()); return user; }; } diff --git a/src/main/java/io/insee/dev/k8sonboarding/configuration/properties/ClusterProperties.java b/src/main/java/io/insee/dev/k8sonboarding/configuration/properties/ClusterProperties.java index 6081cb5..0dba274 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/configuration/properties/ClusterProperties.java +++ b/src/main/java/io/insee/dev/k8sonboarding/configuration/properties/ClusterProperties.java @@ -3,13 +3,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; -import javax.annotation.PostConstruct; - - @Configuration -@ConfigurationProperties(prefix="io.insee.dev.k8sonboarding") +@ConfigurationProperties(prefix = "io.insee.dev.k8sonboarding") public class ClusterProperties { - + private String namespacePrefix; private String namespaceGroupPrefix; private String userPrefix; @@ -22,14 +19,15 @@ public class ClusterProperties { public void setNamespacePrefix(String namespacePrefix) { this.namespacePrefix = namespacePrefix; } - + public String getNameNamespaceAdmin() { return nameNamespaceAdmin; } + public void setNameNamespaceAdmin(String nameNamespaceAdmin) { this.nameNamespaceAdmin = nameNamespaceAdmin; } - + public String getNamespacePrefix() { return namespacePrefix; } @@ -37,6 +35,7 @@ public String getNamespacePrefix() { public String getApiserverUrl() { return apiserverUrl; } + public void setApiserverUrl(String apiserverUrl) { this.apiserverUrl = apiserverUrl; } diff --git a/src/main/java/io/insee/dev/k8sonboarding/configuration/security/CorsFilterConfiguration.java b/src/main/java/io/insee/dev/k8sonboarding/configuration/security/CorsFilterConfiguration.java new file mode 100644 index 0000000..5a6b354 --- /dev/null +++ b/src/main/java/io/insee/dev/k8sonboarding/configuration/security/CorsFilterConfiguration.java @@ -0,0 +1,29 @@ +package io.insee.dev.k8sonboarding.configuration.security; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +public class CorsFilterConfiguration { + + @Value("${io.insee.dev.k8sonboarding.authorized.urls:*}") + private String[] urls; + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOriginPatterns(List.of(urls)); + configuration.setAllowedMethods(List.of("*")); + configuration.setAllowedHeaders(List.of("*")); + configuration.setMaxAge(3600L); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } +} diff --git a/src/main/java/io/insee/dev/k8sonboarding/configuration/security/SecurityConfiguration.java b/src/main/java/io/insee/dev/k8sonboarding/configuration/security/SecurityConfiguration.java index c5fac99..0abb651 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/configuration/security/SecurityConfiguration.java +++ b/src/main/java/io/insee/dev/k8sonboarding/configuration/security/SecurityConfiguration.java @@ -1,26 +1,105 @@ package io.insee.dev.k8sonboarding.configuration.security; +import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.config.Customizer; +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.configurers.AuthorizeHttpRequestsConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; @Configuration +@EnableMethodSecurity public class SecurityConfiguration { + @Value("${io.insee.dev.k8sonboarding.jwt.username-claim:preferred_username}") + private String usernameClaim; + + @Value("${io.insee.dev.k8sonboarding.jwt.groups-claim:groups}") + private String groupsClaim; + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.httpBasic().disable().csrf().disable() - .authorizeRequests() - .antMatchers("/api/public/**").permitAll() - .antMatchers("/api","/api/").permitAll() // For swagger-ui redirection - .antMatchers("/api/**").authenticated() - .anyRequest().permitAll() - .and() - .oauth2ResourceServer() - .jwt(); + http.cors(Customizer.withDefaults()); + http.csrf(csrf -> csrf.disable()); + http.sessionManagement(session -> session.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()) + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + http.oauth2ResourceServer(oauth2 -> oauth2 + .jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter()))); + http.authorizeHttpRequests(this::authorizedUrls); return http.build(); } -} - \ No newline at end of file + private void authorizedUrls( + AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry authorize) { + String[] publicUrls = { "/api/public/**", "/api", "/api/" }; + String[] restrictedUrls = { "/api/**" }; + for (String url : publicUrls) { + authorize.requestMatchers(antMatcher(url)).permitAll(); + } + for (String url : restrictedUrls) { + authorize.requestMatchers(antMatcher(url)).authenticated(); + } + authorize.anyRequest().permitAll(); + } + + private JwtAuthenticationConverter jwtAuthenticationConverter() { + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter()); + jwtAuthenticationConverter.setPrincipalClaimName(usernameClaim); + return jwtAuthenticationConverter; + } + + private Converter> jwtGrantedAuthoritiesConverter() { + return new Converter>() { + @Override + @SuppressWarnings({ "unchecked" }) + public Collection convert(Jwt source) { + String oidcClaimRole = groupsClaim; + String[] claimPath = oidcClaimRole.split("\\."); + Map claims = source.getClaims(); + try { + for (int i = 0; i < claimPath.length - 1; i++) { + claims = (Map) claims.get(claimPath[i]); + } + if (claims == null) { + return Collections.emptyList(); + } + List roles = (List) claims + .getOrDefault(claimPath[claimPath.length - 1], Collections.emptyList()); + return roles.stream() + .map(s -> new GrantedAuthority() { + @Override + public String getAuthority() { + return "ROLE_" + s; + } + + @Override + public String toString() { + return getAuthority(); + } + }) + .collect(Collectors.toList()); + } catch (ClassCastException e) { + // role path not correctly found, assume that no role for this user + return Collections.emptyList(); + } + } + }; + } + +} diff --git a/src/main/java/io/insee/dev/k8sonboarding/configuration/swagger/SwaggerConfiguration.java b/src/main/java/io/insee/dev/k8sonboarding/configuration/swagger/SwaggerConfiguration.java index 305fbc3..b7c384a 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/configuration/swagger/SwaggerConfiguration.java +++ b/src/main/java/io/insee/dev/k8sonboarding/configuration/swagger/SwaggerConfiguration.java @@ -17,10 +17,10 @@ @Configuration public class SwaggerConfiguration { - @Value("${io.insee.dev.k8sonboarding.swagger.oauth2.authUrl}") + @Value("${io.insee.dev.k8sonboarding.swagger.oauth2.authUrl:}") public String authUrl; - @Value("${io.insee.dev.k8sonboarding.swagger.oauth2.tokenUrl}") + @Value("${io.insee.dev.k8sonboarding.swagger.oauth2.tokenUrl:}") public String tokenUrl; public final String SCHEME = "oAuthScheme"; diff --git a/src/main/java/io/insee/dev/k8sonboarding/controller/UserAccessController.java b/src/main/java/io/insee/dev/k8sonboarding/controller/UserAccessController.java index c157886..eef8c24 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/controller/UserAccessController.java +++ b/src/main/java/io/insee/dev/k8sonboarding/controller/UserAccessController.java @@ -1,16 +1,14 @@ package io.insee.dev.k8sonboarding.controller; -import io.insee.dev.k8sonboarding.configuration.security.UserProvider; -import io.insee.dev.k8sonboarding.service.OnboardingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; +import io.insee.dev.k8sonboarding.configuration.security.UserProvider; +import io.insee.dev.k8sonboarding.service.OnboardingService; @RestController @RequestMapping("/api/cluster") diff --git a/src/main/java/io/insee/dev/k8sonboarding/service/OnboardingService.java b/src/main/java/io/insee/dev/k8sonboarding/service/OnboardingService.java index 237e884..b78bde1 100644 --- a/src/main/java/io/insee/dev/k8sonboarding/service/OnboardingService.java +++ b/src/main/java/io/insee/dev/k8sonboarding/service/OnboardingService.java @@ -20,7 +20,6 @@ import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.ResourceQuota; import io.fabric8.kubernetes.api.model.ResourceQuotaBuilder; -import io.fabric8.kubernetes.api.model.ResourceQuotaFluent; import io.fabric8.kubernetes.api.model.rbac.RoleBinding; import io.fabric8.kubernetes.api.model.rbac.RoleBindingBuilder; import io.fabric8.kubernetes.api.model.rbac.SubjectBuilder; @@ -62,7 +61,7 @@ public class OnboardingService { @Autowired private KubernetesClient kubernetesClient; - @Value("${io.insee.dev.k8sonboarding.does-remove-suffix}") + @Value("${io.insee.dev.k8sonboarding.does-remove-suffix:false}") private boolean doesRemoveSuffix; public boolean isDoesRemoveSuffix() { @@ -117,7 +116,7 @@ private void applyQuotas(String namespaceId, QuotaProperties inputQuota, boolean return; } - ResourceQuotaFluent.SpecNested resourceQuotaBuilderSpecNested = resourceQuotaBuilder + var resourceQuotaBuilderSpecNested = resourceQuotaBuilder .withNewSpec(); quotasToApply.entrySet().stream().filter(e -> e.getValue() != null) .forEach(e -> resourceQuotaBuilderSpecNested.addToHard(e.getKey(), Quantity.parse(e.getValue()))); @@ -125,7 +124,7 @@ private void applyQuotas(String namespaceId, QuotaProperties inputQuota, boolean ResourceQuota quota = resourceQuotaBuilder.build(); if (overrideExisting) { - kubernetesClient.resource(quota).inNamespace(namespaceId).createOrReplace(); + kubernetesClient.resource(quota).inNamespace(namespaceId).createOr(t -> t.patch()); } else { try { kubernetesClient.resource(quota).inNamespace(namespaceId).create(); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0dacb91..fef5f63 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,4 +1,5 @@ spring.security.oauth2.resourceserver.jwt.issuer-uri: +io.insee.dev.k8sonboarding.authorized.urls: "*" springdoc.swagger-ui.path: "/api" io.insee.dev.k8sonboarding: @@ -29,4 +30,4 @@ io.insee.dev.k8sonboarding: authority: "https://my_auth_server/auth/realms/my_realm" groupFilter: user-namespace-enabled: true - namespace-creation-allowed: true \ No newline at end of file + namespace-creation-allowed: true diff --git a/src/test/java/io/insee/dev/k8sonboarding/K8sOnboardingApplicationTests.java b/src/test/java/io/insee/dev/k8sonboarding/K8sOnboardingApplicationTests.java deleted file mode 100644 index c9a0fd8..0000000 --- a/src/test/java/io/insee/dev/k8sonboarding/K8sOnboardingApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.insee.dev.k8sonboarding; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class K8sOnboardingApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/io/insee/dev/k8sonboarding/service/OnboardingServiceTests.java b/src/test/java/io/insee/dev/k8sonboarding/service/OnboardingServiceTests.java index 9b5bfb3..027ba7d 100644 --- a/src/test/java/io/insee/dev/k8sonboarding/service/OnboardingServiceTests.java +++ b/src/test/java/io/insee/dev/k8sonboarding/service/OnboardingServiceTests.java @@ -1,45 +1,34 @@ package io.insee.dev.k8sonboarding.service; -import io.fabric8.kubernetes.api.model.NamespaceBuilder; -import io.fabric8.kubernetes.api.model.NamespaceList; -import io.fabric8.kubernetes.api.model.NamespaceListBuilder; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; -import io.fabric8.kubernetes.client.dsl.Resource; -import io.insee.dev.k8sonboarding.configuration.KubernetesClientProvider; -import jdk.jfr.Description; -import org.junit.Assert; +import static org.mockito.Mockito.mock; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.Mockito; -import org.springframework.test.util.ReflectionTestUtils; -import io.fabric8.kubernetes.api.model.Namespace; -import io.fabric8.kubernetes.api.model.rbac.RoleBindingList; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.insee.dev.k8sonboarding.configuration.KubernetesClientProvider; import io.insee.dev.k8sonboarding.configuration.properties.ClusterProperties; import io.insee.dev.k8sonboarding.model.User; -import io.insee.dev.k8sonboarding.view.ClusterCredentials; - -import static org.mockito.Mockito.mock; +import jdk.jfr.Description; public class OnboardingServiceTests { @Mock KubernetesClientProvider kubernetesClientProvider = mock(KubernetesClientProvider.class); @Mock KubernetesClient kubernetesClient = mock(KubernetesClient.class); - private ClusterProperties clusterProperties = new ClusterProperties(); + private ClusterProperties clusterProperties = new ClusterProperties(); - private User user = new User(); + private User user = new User(); private OnboardingService onboardingService; + @BeforeEach - public void setup(){ + public void setup() { Mockito.when(kubernetesClientProvider.getKubernetesClient()).thenReturn(kubernetesClient); - this.onboardingService = new OnboardingService(clusterProperties,kubernetesClientProvider); + this.onboardingService = new OnboardingService(clusterProperties, kubernetesClientProvider); onboardingService.setDoesRemoveSuffix(true); onboardingService.setKubernetesClient(kubernetesClient); clusterProperties.setNamespacePrefix("namespaceprefix-"); @@ -51,80 +40,104 @@ public void setup(){ user.setId("id"); user.setAuthToken("authToken"); } - /** - - @Test - public void checkNamespaceExistsTest() { - // mock.expect().withPath("/api/v1/namespaces/namespaceprefix-userprefix-id") - // .andReturn(200, new NamespaceBuilder().build()).once(); - client.namespaces().createNew().withNewMetadata().withName("namespaceprefix-userprefix-id").endMetadata() - .done(); - final OnboardingService onBoardingService = new OnboardingService(this.clusterProperties, this.client); - Assert.assertEquals(Boolean.TRUE, onBoardingService.checkNamespaceExists("namespaceprefix-userprefix-id")); - } - - @Test - public void checkNamespaceDontExists() { - final OnboardingService onBoardingService = new OnboardingService(this.clusterProperties, this.client); - Assert.assertEquals(Boolean.FALSE, onBoardingService.checkNamespaceExists("namespaceprefix-userprefix-id")); - } - @Test - public void onboardTests() { - final OnboardingService onBoardingService = new OnboardingService(this.clusterProperties, this.client); - ReflectionTestUtils.setField(onBoardingService, "appName", "appName"); - //onBoardingService.onboard(user); - final Namespace namespace = client.namespaces().withName("namespaceprefix-userprefix-id").get(); - Assert.assertEquals(namespace.getMetadata().getLabels().size(), 1); - Assert.assertEquals(namespace.getMetadata().getLabels().get(OnboardingService.LABEL_CREATED_BY), "appName"); - final RoleBindingList roleBindingList = client.rbac().roleBindings() - .inNamespace("namespaceprefix-userprefix-id").list(); - Assert.assertEquals(roleBindingList.getItems().size(), 1); - Assert.assertEquals(roleBindingList.getItems().get(0).getMetadata().getLabels().size(), 1); - Assert.assertEquals( - roleBindingList.getItems().get(0).getMetadata().getLabels().get(OnboardingService.LABEL_CREATED_BY), - "appName"); - Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().size(), 1); - Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getKind(), OnboardingService.USER); - Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getApiGroup(), - OnboardingService.API_GROUP); - Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getName(), user.getId()); - Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getNamespace(), - "namespaceprefix-userprefix-id"); - Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getName(), OnboardingService.ADMIN); - Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getApiGroup(), OnboardingService.API_GROUP); - Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getKind(), OnboardingService.CLUSTER_ROLE); - - } - - @Test - public void clusterCredentialTests() { - final OnboardingService onBoardingService = new OnboardingService(this.clusterProperties, this.client); - final ClusterCredentials clusterCredentials = onBoardingService.getClusterCredentials(user); - Assert.assertEquals("authToken", clusterCredentials.getToken()); - Assert.assertEquals("apiserver-url", clusterCredentials.getApiserverUrl()); - Assert.assertEquals("namespaceprefix-userprefix-id", clusterCredentials.getNamespace()); - Assert.assertEquals("userprefix-id", clusterCredentials.getUser()); - } + /** + * + * @Test + * public void checkNamespaceExistsTest() { + * // + * mock.expect().withPath("/api/v1/namespaces/namespaceprefix-userprefix-id") + * // .andReturn(200, new NamespaceBuilder().build()).once(); + * client.namespaces().createNew().withNewMetadata().withName("namespaceprefix-userprefix-id").endMetadata() + * .done(); + * final OnboardingService onBoardingService = new + * OnboardingService(this.clusterProperties, this.client); + * Assert.assertEquals(Boolean.TRUE, + * onBoardingService.checkNamespaceExists("namespaceprefix-userprefix-id")); + * } + * + * @Test + * public void checkNamespaceDontExists() { + * final OnboardingService onBoardingService = new + * OnboardingService(this.clusterProperties, this.client); + * Assert.assertEquals(Boolean.FALSE, + * onBoardingService.checkNamespaceExists("namespaceprefix-userprefix-id")); + * } + * + * @Test + * public void onboardTests() { + * final OnboardingService onBoardingService = new + * OnboardingService(this.clusterProperties, this.client); + * ReflectionTestUtils.setField(onBoardingService, "appName", "appName"); + * //onBoardingService.onboard(user); + * final Namespace namespace = + * client.namespaces().withName("namespaceprefix-userprefix-id").get(); + * Assert.assertEquals(namespace.getMetadata().getLabels().size(), 1); + * Assert.assertEquals(namespace.getMetadata().getLabels().get(OnboardingService.LABEL_CREATED_BY), + * "appName"); + * final RoleBindingList roleBindingList = client.rbac().roleBindings() + * .inNamespace("namespaceprefix-userprefix-id").list(); + * Assert.assertEquals(roleBindingList.getItems().size(), 1); + * Assert.assertEquals(roleBindingList.getItems().get(0).getMetadata().getLabels().size(), + * 1); + * Assert.assertEquals( + * roleBindingList.getItems().get(0).getMetadata().getLabels().get(OnboardingService.LABEL_CREATED_BY), + * "appName"); + * Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().size(), + * 1); + * Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getKind(), + * OnboardingService.USER); + * Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getApiGroup(), + * OnboardingService.API_GROUP); + * Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getName(), + * user.getId()); + * Assert.assertEquals(roleBindingList.getItems().get(0).getSubjects().get(0).getNamespace(), + * "namespaceprefix-userprefix-id"); + * Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getName(), + * OnboardingService.ADMIN); + * Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getApiGroup(), + * OnboardingService.API_GROUP); + * Assert.assertEquals(roleBindingList.getItems().get(0).getRoleRef().getKind(), + * OnboardingService.CLUSTER_ROLE); + * + * } + * + * @Test + * public void clusterCredentialTests() { + * final OnboardingService onBoardingService = new + * OnboardingService(this.clusterProperties, this.client); + * final ClusterCredentials clusterCredentials = + * onBoardingService.getClusterCredentials(user); + * Assert.assertEquals("authToken", clusterCredentials.getToken()); + * Assert.assertEquals("apiserver-url", + * clusterCredentials.getApiserverUrl()); + * Assert.assertEquals("namespaceprefix-userprefix-id", + * clusterCredentials.getNamespace()); + * Assert.assertEquals("userprefix-id", clusterCredentials.getUser()); + * } * */ @Test() @Description("check that sanitization and removing suffix works on group namespace id") - public void getNamespaceIdShouldBeOk(){ + public void getNamespaceIdShouldBeOk() { String toSanitizeGroup = "observability_K8S-DEV"; - String namespaceId = onboardingService.getNamespaceId(user,toSanitizeGroup); + String namespaceId = onboardingService.getNamespaceId(user, toSanitizeGroup); var grpou = onboardingService.getGroupIdPrefixed(toSanitizeGroup); System.out.println(grpou); System.out.println(toSanitizeGroup); - Assertions.assertEquals("grpprefix-observability",namespaceId); + Assertions.assertEquals("grpprefix-observability", namespaceId); } - /*@Test - @Description("check that role correspond to real kubernetes objects") - public void addPermissionsToNamespaceTest(){ - String toSanitizeGroup = "observability_k8s-dev"; - var mockedNamespace = mock(NonNamespaceOperation.class); - Mockito.when(mockedNamespace); - Mockito.when(kubernetesClient.namespaces()).thenReturn(mockedNamespace); - var roleBinding = onboardingService.addPermissionsToNamespace(user,toSanitizeGroup); - }*/ + /* + * @Test + * + * @Description("check that role correspond to real kubernetes objects") + * public void addPermissionsToNamespaceTest(){ + * String toSanitizeGroup = "observability_k8s-dev"; + * var mockedNamespace = mock(NonNamespaceOperation.class); + * Mockito.when(mockedNamespace); + * Mockito.when(kubernetesClient.namespaces()).thenReturn(mockedNamespace); + * var roleBinding = + * onboardingService.addPermissionsToNamespace(user,toSanitizeGroup); + * } + */ } diff --git a/src/test/java/io/insee/dev/k8sonboarding/testconfiguration/MockedBeans.java b/src/test/java/io/insee/dev/k8sonboarding/testconfiguration/MockedBeans.java deleted file mode 100644 index caffd15..0000000 --- a/src/test/java/io/insee/dev/k8sonboarding/testconfiguration/MockedBeans.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.insee.dev.k8sonboarding.testconfiguration; - -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.jwt.JwtDecoder; - -@Configuration -public class MockedBeans { - - @MockBean - private JwtDecoder jwtDecoder; - -} diff --git a/ui/.env b/ui/.env index 706a1bd..e05f024 100644 --- a/ui/.env +++ b/ui/.env @@ -1,6 +1,6 @@ # API -REACT_APP_API_BASE_URL= +VITE_API_BASE_URL= # AUTH -REACT_APP_OIDC_AUTHORITY= -REACT_APP_OIDC_CLIENT_ID= +VITE_OIDC_AUTHORITY= +VITE_OIDC_CLIENT_ID= diff --git a/ui/.gitignore b/ui/.gitignore index 4d29575..2a5bc17 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -10,7 +10,7 @@ # production /build - +/dist # misc .DS_Store .env.local diff --git a/ui/public/index.html b/ui/index.html similarity index 84% rename from ui/public/index.html rename to ui/index.html index 98dc5ce..a35f964 100644 --- a/ui/public/index.html +++ b/ui/index.html @@ -3,22 +3,22 @@ - + - + - + @@ -28,6 +28,7 @@
+