diff --git a/src/main/java/run/halo/app/config/WebSecurityConfig.java b/src/main/java/run/halo/app/config/WebSecurityConfig.java index 102dbe107..36d0eada1 100644 --- a/src/main/java/run/halo/app/config/WebSecurityConfig.java +++ b/src/main/java/run/halo/app/config/WebSecurityConfig.java @@ -10,7 +10,6 @@ import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; -import java.util.List; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.security.authentication.AuthenticationManager; @@ -33,7 +32,8 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import org.springframework.security.web.context.SecurityContextPersistenceFilter; +import org.springframework.security.web.context.SecurityContextHolderFilter; +import run.halo.app.extension.ExtensionClient; import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService; import run.halo.app.identity.authentication.JwtGenerator; import run.halo.app.identity.authentication.OAuth2AuthorizationService; @@ -44,16 +44,14 @@ import run.halo.app.identity.authentication.ProviderContextFilter; import run.halo.app.identity.authentication.ProviderSettings; import run.halo.app.identity.authentication.verifier.BearerTokenAuthenticationFilter; import run.halo.app.identity.authentication.verifier.JwtProvidedDecoderAuthenticationManagerResolver; -import run.halo.app.identity.authorization.PolicyRule; +import run.halo.app.identity.authorization.DefaultRoleBindingLister; +import run.halo.app.identity.authorization.DefaultRoleGetter; import run.halo.app.identity.authorization.RequestInfoAuthorizationManager; -import run.halo.app.identity.authorization.Role; -import run.halo.app.identity.authorization.RoleBinding; -import run.halo.app.identity.authorization.RoleRef; -import run.halo.app.identity.authorization.Subject; +import run.halo.app.identity.authorization.RoleBindingLister; +import run.halo.app.identity.authorization.RoleGetter; import run.halo.app.identity.entrypoint.JwtAccessDeniedHandler; import run.halo.app.identity.entrypoint.JwtAuthenticationEntryPoint; import run.halo.app.infra.properties.JwtProperties; -import run.halo.app.infra.types.ObjectMeta; /** * @author guqing @@ -69,11 +67,15 @@ public class WebSecurityConfig { private final AuthenticationManagerBuilder authenticationManagerBuilder; + private final ExtensionClient extensionClient; + public WebSecurityConfig(JwtProperties jwtProperties, - AuthenticationManagerBuilder authenticationManagerBuilder) throws IOException { + AuthenticationManagerBuilder authenticationManagerBuilder, + ExtensionClient extensionClient) throws IOException { this.key = jwtProperties.readPublicKey(); this.priv = jwtProperties.readPrivateKey(); this.authenticationManagerBuilder = authenticationManagerBuilder; + this.extensionClient = extensionClient; } @Bean @@ -97,7 +99,7 @@ public class WebSecurityConfig { FilterSecurityInterceptor.class) .addFilterBefore(new BearerTokenAuthenticationFilter(authenticationManagerResolver()), BasicAuthenticationFilter.class) - .addFilterAfter(providerContextFilter, SecurityContextPersistenceFilter.class) + .addFilterAfter(providerContextFilter, SecurityContextHolderFilter.class) .sessionManagement( (session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .exceptionHandling((exceptions) -> exceptions @@ -107,47 +109,10 @@ public class WebSecurityConfig { return http.build(); } - public RequestInfoAuthorizationManager requestInfoAuthorizationManager() { - // TODO fake role and role bindings, only used for testing/development - // It'll be deleted next time - return new RequestInfoAuthorizationManager(name -> { - // role getter - Role role = new Role(); - List rules = List.of( - new PolicyRule.Builder().apiGroups("").resources("posts").verbs("list", "get") - .build(), - new PolicyRule.Builder().apiGroups("").resources("categories").verbs("*") - .build(), - new PolicyRule.Builder().nonResourceURLs("/healthy").verbs("get", "post", "head") - .build() - ); - role.setRules(rules); - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setName("ruleReadPost"); - role.setObjectMeta(objectMeta); - return role; - }, () -> { - // role binding lister - RoleBinding roleBinding = new RoleBinding(); - - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setName("userRoleBinding"); - roleBinding.setObjectMeta(objectMeta); - - Subject subject = new Subject(); - subject.setName("user"); - subject.setKind("User"); - subject.setApiGroup(""); - roleBinding.setSubjects(List.of(subject)); - - RoleRef roleRef = new RoleRef(); - roleRef.setKind("Role"); - roleRef.setName("ruleReadPost"); - roleRef.setApiGroup(""); - roleBinding.setRoleRef(roleRef); - - return List.of(roleBinding); - }); + RequestInfoAuthorizationManager requestInfoAuthorizationManager() { + RoleBindingLister roleBindingLister = new DefaultRoleBindingLister(); + RoleGetter roleGetter = new DefaultRoleGetter(extensionClient); + return new RequestInfoAuthorizationManager(roleGetter, roleBindingLister); } AuthenticationManagerResolver authenticationManagerResolver() { diff --git a/src/main/java/run/halo/app/identity/authorization/DefaultRoleBindingLister.java b/src/main/java/run/halo/app/identity/authorization/DefaultRoleBindingLister.java new file mode 100644 index 000000000..66f3b21c6 --- /dev/null +++ b/src/main/java/run/halo/app/identity/authorization/DefaultRoleBindingLister.java @@ -0,0 +1,90 @@ +package run.halo.app.identity.authorization; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import run.halo.app.extension.Metadata; + +/** + *

Obtain the authorities from the authenticated authentication and construct it as a RoleBinding + * list.

+ *

After JWT authentication, the roles stored in the authorities are the roles owned by the user, + * so there is no need to query from the database.

+ *

For tokens in other formats, after authentication, fill the authorities with the token into + * the SecurityContextHolder.

+ *
+ * kind: RoleBinding
+ * metadata:
+ *   name: some-name
+ * subjects:
+ * # You can specify more than one "subject"
+ * - kind: User
+ *   name: some-username
+ * roleRef:
+ *   kind: Role
+ *   name: role-name
+ * 
+ * + * @author guqing + * @since 2.0.0 + */ +public class DefaultRoleBindingLister implements RoleBindingLister { + private static final String SCOPE_AUTHORITY_PREFIX = "SCOPE_"; + private static final String ROLE_AUTHORITY_PREFIX = "ROLE_"; + + @Override + public List listRoleBindings() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication == null) { + return Collections.emptyList(); + } + String username = authentication.getName(); + + List roleNames = roleNamesFromAuthentication(); + + List roleBindings = new ArrayList<>(roleNames.size()); + for (String roleName : roleNames) { + RoleBinding roleBinding = new RoleBinding(); + // metadata + Metadata metadata = new Metadata(); + metadata.setName(username + "_" + roleName); + roleBinding.setMetadata(metadata); + + // role ref + RoleRef roleRef = new RoleRef(); + roleRef.setKind("Role"); + roleRef.setName(roleName); + roleBinding.setRoleRef(roleRef); + + // subject + Subject subject = new Subject(); + subject.setKind("User"); + subject.setName(username); + roleBinding.setSubjects(List.of(subject)); + roleBindings.add(roleBinding); + } + return roleBindings; + } + + private List roleNamesFromAuthentication() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + return authentication.getAuthorities() + .stream() + .map(GrantedAuthority::getAuthority) + .map(scope -> { + if (scope.startsWith(SCOPE_AUTHORITY_PREFIX)) { + return scope.replaceFirst(SCOPE_AUTHORITY_PREFIX, ""); + } + if (scope.startsWith(ROLE_AUTHORITY_PREFIX)) { + return scope.replaceFirst(ROLE_AUTHORITY_PREFIX, ""); + } + return scope; + }) + .toList(); + } +} diff --git a/src/main/java/run/halo/app/identity/authorization/DefaultRoleGetter.java b/src/main/java/run/halo/app/identity/authorization/DefaultRoleGetter.java new file mode 100644 index 000000000..fa1a63c41 --- /dev/null +++ b/src/main/java/run/halo/app/identity/authorization/DefaultRoleGetter.java @@ -0,0 +1,25 @@ +package run.halo.app.identity.authorization; + +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import run.halo.app.extension.ExtensionClient; + +/** + * @author guqing + * @since 2.0.0 + */ +@Component +public class DefaultRoleGetter implements RoleGetter { + + private final ExtensionClient extensionClient; + + public DefaultRoleGetter(ExtensionClient extensionClient) { + this.extensionClient = extensionClient; + } + + @Override + @NonNull + public Role getRole(@NonNull String name) { + return extensionClient.fetch(Role.class, name).orElseThrow(); + } +} diff --git a/src/main/java/run/halo/app/identity/authorization/DefaultRuleResolver.java b/src/main/java/run/halo/app/identity/authorization/DefaultRuleResolver.java index 9b6ceee76..c1ad05020 100644 --- a/src/main/java/run/halo/app/identity/authorization/DefaultRuleResolver.java +++ b/src/main/java/run/halo/app/identity/authorization/DefaultRuleResolver.java @@ -76,7 +76,7 @@ public class DefaultRuleResolver implements AuthorizationRuleResolver { String roleBindingDescriber(RoleBinding roleBinding, Subject subject) { String describeSubject = String.format("%s %s", subject.kind, subject.name); - return String.format("RoleBinding %s of %s %s to %s", roleBinding.getName(), + return String.format("RoleBinding %s of %s %s to %s", roleBinding.metadata().getName(), roleBinding.roleRef.getKind(), roleBinding.roleRef.getName(), describeSubject); } diff --git a/src/main/java/run/halo/app/identity/authorization/PolicyRule.java b/src/main/java/run/halo/app/identity/authorization/PolicyRule.java index 9cbfcc56c..f18f4d138 100644 --- a/src/main/java/run/halo/app/identity/authorization/PolicyRule.java +++ b/src/main/java/run/halo/app/identity/authorization/PolicyRule.java @@ -6,7 +6,7 @@ import lombok.NoArgsConstructor; /** * PolicyRule holds information that describes a policy rule, but does not contain information - * about who the rule applies to or which namespace the rule applies to. + * about whom the rule applies to or which namespace the rule applies to. * * @author guqing * @since 2.0.0 diff --git a/src/main/java/run/halo/app/identity/authorization/Role.java b/src/main/java/run/halo/app/identity/authorization/Role.java index ec4d6f0a2..db9b785fe 100644 --- a/src/main/java/run/halo/app/identity/authorization/Role.java +++ b/src/main/java/run/halo/app/identity/authorization/Role.java @@ -1,20 +1,23 @@ package run.halo.app.identity.authorization; +import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; import lombok.Data; -import run.halo.app.infra.types.ObjectMeta; -import run.halo.app.infra.types.TypeMeta; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import run.halo.app.extension.AbstractExtension; +import run.halo.app.extension.GVK; /** * @author guqing * @since 2.0.0 */ @Data -public class Role { - - TypeMeta typeMeta; - - ObjectMeta objectMeta; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@GVK(group = "", version = "v1alpha1", kind = "Role", plural = "roles", singular = "role") +public class Role extends AbstractExtension { + @Schema(minLength = 1) List rules; } diff --git a/src/main/java/run/halo/app/identity/authorization/RoleBinding.java b/src/main/java/run/halo/app/identity/authorization/RoleBinding.java index 53100042f..b50602c26 100644 --- a/src/main/java/run/halo/app/identity/authorization/RoleBinding.java +++ b/src/main/java/run/halo/app/identity/authorization/RoleBinding.java @@ -2,26 +2,25 @@ package run.halo.app.identity.authorization; import java.util.List; import lombok.Data; -import org.apache.commons.lang3.StringUtils; -import run.halo.app.infra.types.ObjectMeta; -import run.halo.app.infra.types.TypeMeta; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import run.halo.app.extension.AbstractExtension; +import run.halo.app.extension.GVK; /** - * // RoleBinding references a role, but does not contain it. It can reference a Role in the - * same namespace or a ClusterRole in the global namespace. - * // It adds who information via Subjects and namespace information by which namespace it exists - * in. RoleBindings in a given - * // namespace only have effect in that namespace. + * RoleBinding references a role, but does not contain it. + * It can reference a Role in the global. + * It adds who information via Subjects. * * @author guqing * @since 2.0.0 */ @Data -public class RoleBinding { - - TypeMeta typeMeta; - - ObjectMeta objectMeta; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@GVK(group = "", version = "v1alpha1", kind = "RoleBinding", plural = "rolebindings", + singular = "rolebinding") +public class RoleBinding extends AbstractExtension { /** * Subjects holds references to the objects the role applies to. @@ -34,11 +33,4 @@ public class RoleBinding { * If the RoleRef cannot be resolved, the Authorizer must return an error. */ RoleRef roleRef; - - public String getName() { - if (objectMeta == null) { - return StringUtils.EMPTY; - } - return objectMeta.getName(); - } } diff --git a/src/main/java/run/halo/app/identity/authorization/RoleBindingLister.java b/src/main/java/run/halo/app/identity/authorization/RoleBindingLister.java index 608207bc8..8c67502ef 100644 --- a/src/main/java/run/halo/app/identity/authorization/RoleBindingLister.java +++ b/src/main/java/run/halo/app/identity/authorization/RoleBindingLister.java @@ -8,5 +8,6 @@ import java.util.List; */ @FunctionalInterface public interface RoleBindingLister { + List listRoleBindings(); } diff --git a/src/main/java/run/halo/app/infra/SchemeInitializer.java b/src/main/java/run/halo/app/infra/SchemeInitializer.java new file mode 100644 index 000000000..a49822493 --- /dev/null +++ b/src/main/java/run/halo/app/infra/SchemeInitializer.java @@ -0,0 +1,19 @@ +package run.halo.app.infra; + +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import run.halo.app.extension.Schemes; +import run.halo.app.identity.authorization.Role; + +/** + * @author guqing + * @since 2.0.0 + */ +@Component +public class SchemeInitializer implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationStartedEvent event) { + Schemes.INSTANCE.register(Role.class); + } +} diff --git a/src/main/java/run/halo/app/infra/types/ObjectMeta.java b/src/main/java/run/halo/app/infra/types/ObjectMeta.java deleted file mode 100644 index bd7470a4b..000000000 --- a/src/main/java/run/halo/app/infra/types/ObjectMeta.java +++ /dev/null @@ -1,94 +0,0 @@ -package run.halo.app.infra.types; - -import java.time.LocalDateTime; -import java.util.UUID; -import lombok.Data; - -/** - * ObjectMeta is metadata that all persisted resources must have, which includes all objects - * users must create. - * - * @author guqing - * @since 2.0.0 - */ -@Data -public class ObjectMeta { - - /** - * Name must be unique within a namespace. Is required when creating resources, although - * some resources may allow a client to request the generation of an appropriate name - * automatically. Name is primarily intended for creation idempotence and configuration - * definition. - * Cannot be updated. - * Cannot be updated. - * More info: names - * +optional - */ - String name; - - /** - * GenerateName is an optional prefix, used by the server, to generate a unique - * name ONLY IF the Name field has not been provided. - * If this field is used, the name returned to the client will be different - * than the name passed. This value will also be combined with a unique suffix. - * The provided value has the same validation rules as the Name field, - * and may be truncated by the length of the suffix required to make the value - * unique on the server. - *

- * If this field is specified and the generated name exists, the server will return a 409. - *

- * Applied only if Name is not specified. - * More info: - * idempotency - * +optional - */ - String generateName; - - /** - * UID is the unique in time and space value for this object. It is typically generated by - * the server on successful creation of a resource and is not allowed to change on PUT - * operations. - *

- * Populated by the system. - * Read-only. - * More info: uids - * +optional - */ - UUID uid; - - /** - * An opaque value that represents the internal version of this object that can - * be used by clients to determine when objects have changed. May be used for optimistic - * concurrency, change detection, and the watch operation on a resource or set of resources. - * Clients must treat these values as opaque and passed unmodified back to the server. - * They may only be valid for a particular resource or set of resources. - *

- * Populated by the system. - * Read-only. - * Value must be treated as opaque by clients and . - * More info: - * concurrency-control-and-consistency - */ - String resourceVersion; - - /** - * A sequence number representing a specific generation of the desired state. - * Populated by the system. Read-only. - * +optional - */ - Long generation; - - /** - * CreationTimestamp is a timestamp representing the server time when this object was - * created. It is not guaranteed to be set in happens-before order across separate operations. - * Clients may not set this value. It is represented in RFC3339 form and is in UTC. - *

- * Populated by the system. - * Read-only. - * Null for lists. - * More info: - * metadata - * +optional - */ - LocalDateTime creationTimestamp; -} diff --git a/src/main/java/run/halo/app/infra/types/TypeMeta.java b/src/main/java/run/halo/app/infra/types/TypeMeta.java deleted file mode 100644 index 9b47ecdc0..000000000 --- a/src/main/java/run/halo/app/infra/types/TypeMeta.java +++ /dev/null @@ -1,36 +0,0 @@ -package run.halo.app.infra.types; - -import lombok.Data; - -/** - * TypeMeta describes an individual object in an API response or request - * with strings representing the type of the object and its API schema version. - * Structures that are versioned or persisted should inline TypeMeta. - * - * @author guqing - * @since 2.0.0 - */ -@Data -public class TypeMeta { - - /** - * Kind is a string value representing the REST resource this object represents. - * Servers may infer this from the endpoint the client submits requests to. - * Cannot be updated. - * In CamelCase. - * More info: - * resources - * +optional - */ - String apiVersion; -} diff --git a/src/test/java/run/halo/app/authorization/DefaultRoleBindingListerTest.java b/src/test/java/run/halo/app/authorization/DefaultRoleBindingListerTest.java new file mode 100644 index 000000000..8215bb643 --- /dev/null +++ b/src/test/java/run/halo/app/authorization/DefaultRoleBindingListerTest.java @@ -0,0 +1,59 @@ +package run.halo.app.authorization; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import run.halo.app.identity.authorization.DefaultRoleBindingLister; +import run.halo.app.identity.authorization.RoleBinding; + +/** + * Tests for {@link DefaultRoleBindingLister}. + * + * @author guqing + * @since 2.0.0 + */ +@ExtendWith(SpringExtension.class) +public class DefaultRoleBindingListerTest { + + private DefaultRoleBindingLister roleBindingLister; + + @BeforeEach + void setUp() { + roleBindingLister = new DefaultRoleBindingLister(); + } + + @Test + @WithMockUser(username = "test", roles = {"readPost", "readTag"}) + void listWhenAuthorizedWithTwoRoles() { + List roleBindings = roleBindingLister.listRoleBindings(); + assertThat(roleBindings).isNotNull(); + assertThat(roleBindings.size()).isEqualTo(2); + + RoleBinding readPostRoleBinding = roleBindings.get(0); + assertThat(readPostRoleBinding.getMetadata()).isNotNull(); + assertThat(readPostRoleBinding.getMetadata().getName()).isNotNull(); + assertThat(readPostRoleBinding.getSubjects()).allMatch(subject -> + "test".equals(subject.getName()) + && "User".equals(subject.getKind())); + assertThat(readPostRoleBinding.getRoleRef().getName()).isEqualTo("readPost"); + + RoleBinding readTagRoleBinding = roleBindings.get(1); + assertThat(readTagRoleBinding.getMetadata()).isNotNull(); + assertThat(readTagRoleBinding.getMetadata().getName()).isNotNull(); + assertThat(readTagRoleBinding.getSubjects()).allMatch(subject -> + "test".equals(subject.getName()) + && "User".equals(subject.getKind())); + assertThat(readTagRoleBinding.getRoleRef().getName()).isEqualTo("readTag"); + } + + @Test + void listWhenUnauthorizedThenEmpty() { + List roleBindings = roleBindingLister.listRoleBindings(); + assertThat(roleBindings).isEmpty(); + } +} diff --git a/src/test/java/run/halo/app/authorization/RequestInfoResolverTest.java b/src/test/java/run/halo/app/authorization/RequestInfoResolverTest.java index d001da5f3..fb388d296 100644 --- a/src/test/java/run/halo/app/authorization/RequestInfoResolverTest.java +++ b/src/test/java/run/halo/app/authorization/RequestInfoResolverTest.java @@ -13,6 +13,7 @@ import org.springframework.security.core.userdetails.User; import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; +import run.halo.app.extension.Metadata; import run.halo.app.identity.authorization.AttributesRecord; import run.halo.app.identity.authorization.DefaultRuleResolver; import run.halo.app.identity.authorization.PolicyRule; @@ -23,7 +24,6 @@ import run.halo.app.identity.authorization.Role; import run.halo.app.identity.authorization.RoleBinding; import run.halo.app.identity.authorization.RoleRef; import run.halo.app.identity.authorization.Subject; -import run.halo.app.infra.types.ObjectMeta; /** * Tests for {@link RequestInfoFactory}. @@ -131,13 +131,16 @@ public class RequestInfoResolverTest { .build() ); role.setRules(rules); - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setName("ruleReadPost"); - role.setObjectMeta(objectMeta); + Metadata metadata = new Metadata(); + metadata.setName("ruleReadPost"); + role.setMetadata(metadata); return role; }, () -> { // role binding lister RoleBinding roleBinding = new RoleBinding(); + Metadata metadata = new Metadata(); + metadata.setName("admin_ruleReadPost"); + roleBinding.setMetadata(metadata); Subject subject = new Subject(); subject.setName("admin"); diff --git a/src/test/java/run/halo/app/integration/security/TestWebSecurityConfig.java b/src/test/java/run/halo/app/integration/security/TestWebSecurityConfig.java index 00efe7b30..a2dcd4a5b 100644 --- a/src/test/java/run/halo/app/integration/security/TestWebSecurityConfig.java +++ b/src/test/java/run/halo/app/integration/security/TestWebSecurityConfig.java @@ -36,6 +36,7 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.context.SecurityContextPersistenceFilter; import org.springframework.test.context.TestPropertySource; +import run.halo.app.extension.Metadata; import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService; import run.halo.app.identity.authentication.JwtGenerator; import run.halo.app.identity.authentication.OAuth2AuthorizationService; @@ -53,7 +54,6 @@ import run.halo.app.identity.authorization.RoleBinding; import run.halo.app.identity.authorization.RoleRef; import run.halo.app.identity.authorization.Subject; import run.halo.app.infra.properties.JwtProperties; -import run.halo.app.infra.types.ObjectMeta; /** * @author guqing @@ -115,17 +115,17 @@ public class TestWebSecurityConfig { .build() ); role.setRules(rules); - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setName("ruleReadPost"); - role.setObjectMeta(objectMeta); + Metadata metadata = new Metadata(); + metadata.setName("ruleReadPost"); + role.setMetadata(metadata); return role; }, () -> { // role binding lister RoleBinding roleBinding = new RoleBinding(); - ObjectMeta objectMeta = new ObjectMeta(); - objectMeta.setName("userRoleBinding"); - roleBinding.setObjectMeta(objectMeta); + Metadata metadata = new Metadata(); + metadata.setName("userRoleBinding"); + roleBinding.setMetadata(metadata); Subject subject = new Subject(); subject.setName("test_user");