diff --git a/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java b/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java new file mode 100644 index 000000000..e6e09e9ee --- /dev/null +++ b/address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * 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 + * + * http://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 com.alibaba.nacos.address.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +/** + * nacos web security configuration. + * @author onewe + */ +@Configuration +@Order(99) +public class AddressServerSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(requestMatcherRegistry -> requestMatcherRegistry.mvcMatchers("/nacos/v1/as/**").authenticated()) + .csrf().disable().httpBasic(); + } +} diff --git a/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java index f3ceff70e..285b279ba 100644 --- a/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java +++ b/address/src/test/java/com/alibaba/nacos/address/AddressServerControllerTests.java @@ -16,37 +16,36 @@ package com.alibaba.nacos.address; +import com.alibaba.nacos.common.codec.Base64; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration; -import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.LinkedMultiValueMap; +import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@ImportAutoConfiguration(exclude = {SecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class, - ManagementWebSecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = { + "spring.security.user.password=123456", "spring.security.user.name=user"}) public class AddressServerControllerTests { private static final String PRODUCT_CONFIG = "config"; private static final String PRODUCT_NAMING = "naming"; + private static final String HTTP_BASIC_INFO = getHttpBasicInfo(); + @Autowired private TestRestTemplate restTemplate; @@ -56,8 +55,25 @@ public class AddressServerControllerTests { System.setProperty("embeddedStorage", "true"); } + @AfterClass + public static void teardown() { + System.clearProperty("nacos.standalone"); + System.clearProperty("embeddedStorage"); + } + + private static String getHttpBasicInfo() { + String userName = "user"; + String password = "123456"; + + String info = userName + ":" + password; + + final byte[] bytes = Base64.encodeBase64(info.getBytes(StandardCharsets.UTF_8)); + + return "Basic " + new String(bytes, StandardCharsets.UTF_8); + } + @Test - public void postCluster() throws InterruptedException { + public void postClusterWithoutLogin() { String ips = "127.0.0.100,127.0.0.102,127.0.0.104"; LinkedMultiValueMap params = new LinkedMultiValueMap<>(1); @@ -66,9 +82,23 @@ public class AddressServerControllerTests { final ResponseEntity postClusterResponseEntity = restTemplate.exchange( RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + Assert.assertEquals(postClusterResponseEntity.getStatusCode(), HttpStatus.UNAUTHORIZED); + } + + @Test + public void postCluster() throws InterruptedException { + + String ips = "127.0.0.100,127.0.0.102,127.0.0.104"; + LinkedMultiValueMap params = new LinkedMultiValueMap<>(1); + params.add("ips", ips); + + final ResponseEntity postClusterResponseEntity = restTemplate.exchange( + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); + Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity getClusterResponseEntity = restTemplate.exchange( @@ -79,6 +109,16 @@ public class AddressServerControllerTests { } + @Test + public void deleteClusterWithoutLogin() { + LinkedMultiValueMap params = new LinkedMultiValueMap<>(1); + params.add("ips", "127.0.0.104"); + + final ResponseEntity postClusterResponseEntity = restTemplate.exchange( + RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + Assert.assertEquals(postClusterResponseEntity.getStatusCode(), HttpStatus.UNAUTHORIZED); + } + @Test public void deleteCluster() throws InterruptedException { @@ -86,15 +126,17 @@ public class AddressServerControllerTests { params.add("ips", "127.0.0.104"); final ResponseEntity postClusterResponseEntity = restTemplate.exchange( - RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange( - RequestEntity.delete("/nacos/v1/as/nodes?ips={ips}", "127.0.0.104").build(), String.class); + RequestEntity.delete("/nacos/v1/as/nodes?ips={ips}", "127.0.0.104") + .header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(), String.class); Assert.assertNotNull(deleteClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue()); @@ -110,10 +152,11 @@ public class AddressServerControllerTests { params.add("product", PRODUCT_CONFIG); final ResponseEntity postClusterResponseEntity = restTemplate.exchange( - RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity getClusterResponseEntity = restTemplate.exchange( @@ -134,15 +177,16 @@ public class AddressServerControllerTests { params.add("product", PRODUCT_CONFIG); final ResponseEntity postClusterResponseEntity = restTemplate.exchange( - RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange( RequestEntity.delete("/nacos/v1/as/nodes?product={product}&ips={ips}", PRODUCT_CONFIG, "127.0.0.104") - .build(), String.class); + .header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(), String.class); Assert.assertNotNull(deleteClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue()); @@ -159,10 +203,11 @@ public class AddressServerControllerTests { params.add("cluster", "cluster01"); final ResponseEntity postClusterResponseEntity = restTemplate.exchange( - RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity getClusterResponseEntity = restTemplate.exchange( @@ -184,24 +229,20 @@ public class AddressServerControllerTests { params.add("cluster", "cluster01"); final ResponseEntity postClusterResponseEntity = restTemplate.exchange( - RequestEntity.post("/nacos/v1/as/nodes").body(params), String.class); + RequestEntity.post("/nacos/v1/as/nodes").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO) + .body(params), String.class); Assert.assertNotNull(postClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), postClusterResponseEntity.getStatusCodeValue()); - + TimeUnit.MILLISECONDS.sleep(500L); final ResponseEntity deleteClusterResponseEntity = restTemplate.exchange( RequestEntity.delete("/nacos/v1/as/nodes?product={product}&cluster={cluster}&ips={ips}", PRODUCT_NAMING, - "cluster01", "127.0.0.104").build(), String.class); + "cluster01", "127.0.0.104").header(HttpHeaders.AUTHORIZATION, HTTP_BASIC_INFO).build(), + String.class); Assert.assertNotNull(deleteClusterResponseEntity); Assert.assertEquals(HttpStatus.OK.value(), deleteClusterResponseEntity.getStatusCodeValue()); } - @AfterClass - public static void teardown() { - System.clearProperty("nacos.standalone"); - System.clearProperty("embeddedStorage"); - } - }