Skip to content

Commit

Permalink
Merge branch 'spring-projects:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilpyo-Yang committed Mar 16, 2024
2 parents 7b3eb88 + 0078462 commit 4f82c8c
Show file tree
Hide file tree
Showing 38 changed files with 3,181 additions and 351 deletions.
51 changes: 45 additions & 6 deletions .github/workflows/merge-dependabot-pr.yml
@@ -1,13 +1,52 @@
name: Merge Dependabot PR

on:
pull_request:
on: pull_request_target

run-name: Merge Dependabot PR ${{ github.ref_name }}

permissions: write-all

jobs:
merge-dependabot-pr:
permissions: write-all
uses: spring-io/spring-github-workflows/.github/workflows/spring-merge-dependabot-pr.yml@1e8b0587a1f4f01697f9753fa3339c3e0d30f396
with:
mergeArguments: '--auto --rebase'
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:

- uses: actions/checkout@v4
with:
show-progress: false
ref: ${{ github.event.pull_request.head.sha }}

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- name: Set Milestone to Dependabot Pull Request
id: set-milestone
run: |
if test -f pom.xml
then
CURRENT_VERSION=$(mvn help:evaluate -Dexpression="project.version" -q -DforceStdout)
else
CURRENT_VERSION=$(cat gradle.properties | sed -n '/^version=/ { s/^version=//;p }')
fi
export CANDIDATE_VERSION=${CURRENT_VERSION/-SNAPSHOT}
MILESTONE=$(gh api repos/$GITHUB_REPOSITORY/milestones --jq 'map(select(.due_on != null and (.title | startswith(env.CANDIDATE_VERSION)))) | .[0] | .title')
if [ -z $MILESTONE ]
then
gh run cancel ${{ github.run_id }}
echo "::warning title=Cannot merge::No scheduled milestone for $CURRENT_VERSION version"
else
gh pr edit ${{ github.event.pull_request.number }} --milestone $MILESTONE
echo mergeEnabled=true >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Merge Dependabot pull request
if: steps.set-milestone.outputs.mergeEnabled
run: gh pr merge ${{ github.event.pull_request.number }} --auto --rebase
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
7 changes: 4 additions & 3 deletions .github/workflows/trigger-dependabot-auto-merge-forward.yml
@@ -1,16 +1,17 @@
name: Trigger Dependabot Auto Merge Forward

on:
pull_request:
types: [closed]
push:
branches:
- '*.x'

permissions: read-all

jobs:
trigger-worflow:
name: Trigger Workflow
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.merged == true && github.actor == 'dependabot[bot]' && github.repository == 'spring-projects/spring-security' }}
if: ${{ github.event.commits[0].author.username == 'dependabot[bot]' && github.repository == 'spring-projects/spring-security' }}
steps:
- name: Checkout
id: checkout
Expand Down
@@ -0,0 +1,44 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.config.annotation.method.configuration;

import java.util.ArrayList;
import java.util.List;

import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.AuthorizationAdvisorProxyFactory;
import org.springframework.security.authorization.method.AuthorizationAdvisor;

@Configuration(proxyBeanMethods = false)
final class AuthorizationProxyConfiguration implements AopInfrastructureBean {

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static AuthorizationAdvisorProxyFactory authorizationProxyFactory(ObjectProvider<AuthorizationAdvisor> provider) {
List<AuthorizationAdvisor> advisors = new ArrayList<>();
provider.forEach(advisors::add);
AuthorizationAdvisorProxyFactory factory = new AuthorizationAdvisorProxyFactory();
factory.setAdvisors(advisors);
return factory;
}

}
Expand Up @@ -20,6 +20,7 @@
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -48,7 +49,7 @@
*/
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
final class Jsr250MethodSecurityConfiguration implements ImportAware {
final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {

private int interceptorOrderOffset;

Expand Down
Expand Up @@ -56,6 +56,7 @@ public String[] selectImports(@NonNull AnnotationMetadata importMetadata) {
if (annotation.jsr250Enabled()) {
imports.add(Jsr250MethodSecurityConfiguration.class.getName());
}
imports.add(AuthorizationProxyConfiguration.class.getName());
return imports.toArray(new String[0]);
}

Expand Down
Expand Up @@ -27,7 +27,6 @@
import org.jetbrains.annotations.Nullable;

import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
Expand All @@ -36,14 +35,14 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.method.AuthorizationAdvisor;
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
Expand All @@ -65,7 +64,7 @@
*/
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
final class PrePostMethodSecurityConfiguration implements ImportAware {
final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {

private int interceptorOrderOffset;

Expand Down Expand Up @@ -175,8 +174,8 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
this.interceptorOrderOffset = annotation.offset();
}

private static final class DeferringMethodInterceptor<M extends Ordered & MethodInterceptor & PointcutAdvisor>
implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
implements AuthorizationAdvisor {

private final Pointcut pointcut;

Expand Down
Expand Up @@ -16,9 +16,18 @@

package org.springframework.security.config.annotation.method.configuration;

import java.util.function.Consumer;
import java.util.function.Supplier;

import io.micrometer.observation.ObservationRegistry;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
Expand All @@ -29,6 +38,7 @@
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.authorization.method.AuthorizationAdvisor;
import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
import org.springframework.security.authorization.method.MethodInvocationResult;
Expand All @@ -38,6 +48,7 @@
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.util.function.SingletonSupplier;

/**
* Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
Expand All @@ -46,54 +57,56 @@
* @since 5.8
*/
@Configuration(proxyBeanMethods = false)
final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements AopInfrastructureBean {

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
MethodSecurityExpressionHandler expressionHandler,
static MethodInterceptor preFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
expressionHandler);
defaultsObjectProvider.ifAvailable(interceptor::setTemplateDefaults);
return interceptor;
return new DeferringMethodInterceptor<>(interceptor,
(i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
MethodSecurityExpressionHandler expressionHandler,
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
ObjectProvider<ObservationRegistry> registryProvider) {
PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
expressionHandler);
defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults);
ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(manager, registryProvider);
return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
AuthorizationAdvisor interceptor = AuthorizationManagerBeforeReactiveMethodInterceptor
.preAuthorize(authorizationManager);
return new DeferringMethodInterceptor<>(interceptor,
(i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
MethodSecurityExpressionHandler expressionHandler,
static MethodInterceptor postFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
expressionHandler);
defaultsObjectProvider.ifAvailable(interceptor::setTemplateDefaults);
return interceptor;
return new DeferringMethodInterceptor<>(interceptor,
(i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
MethodSecurityExpressionHandler expressionHandler,
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
ObjectProvider<ObservationRegistry> registryProvider) {
PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
expressionHandler);
ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(manager, registryProvider);
defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults);
return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
AuthorizationAdvisor interceptor = AuthorizationManagerAfterReactiveMethodInterceptor
.postAuthorize(authorizationManager);
return new DeferringMethodInterceptor<>(interceptor,
(i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
}

@Bean
Expand All @@ -112,4 +125,50 @@ static <T> ReactiveAuthorizationManager<T> manager(ReactiveAuthorizationManager<
return new DeferringObservationReactiveAuthorizationManager<>(registryProvider, delegate);
}

private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
implements AuthorizationAdvisor {

private final Pointcut pointcut;

private final int order;

private final Supplier<M> delegate;

DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
this.pointcut = delegate.getPointcut();
this.order = delegate.getOrder();
this.delegate = SingletonSupplier.of(() -> {
supplier.accept(delegate);
return delegate;
});
}

@Nullable
@Override
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
return this.delegate.get().invoke(invocation);
}

@Override
public Pointcut getPointcut() {
return this.pointcut;
}

@Override
public Advice getAdvice() {
return this;
}

@Override
public int getOrder() {
return this.order;
}

@Override
public boolean isPerInstance() {
return true;
}

}

}
@@ -0,0 +1,45 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.config.annotation.method.configuration;

import java.util.ArrayList;
import java.util.List;

import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.ReactiveAuthorizationAdvisorProxyFactory;
import org.springframework.security.authorization.method.AuthorizationAdvisor;

@Configuration(proxyBeanMethods = false)
final class ReactiveAuthorizationProxyConfiguration implements AopInfrastructureBean {

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static ReactiveAuthorizationAdvisorProxyFactory authorizationProxyFactory(
ObjectProvider<AuthorizationAdvisor> provider) {
List<AuthorizationAdvisor> advisors = new ArrayList<>();
provider.forEach(advisors::add);
ReactiveAuthorizationAdvisorProxyFactory factory = new ReactiveAuthorizationAdvisorProxyFactory();
factory.setAdvisors(advisors);
return factory;
}

}

0 comments on commit 4f82c8c

Please sign in to comment.