AMBARI-24952 - Infra Manager: basic authentication (#19)

diff --git a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
index fdccbab..1b0b4cf 100644
--- a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
+++ b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
@@ -29,13 +29,17 @@
 import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
 import org.apache.http.impl.client.HttpClientBuilder;
@@ -60,7 +64,16 @@
     } catch (URISyntaxException e) {
       throw new RuntimeException(e);
     }
-    httpClient = HttpClientBuilder.create().setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();
+
+    CredentialsProvider provider = new BasicCredentialsProvider();
+    UsernamePasswordCredentials credentials
+            = new UsernamePasswordCredentials("admin", "admin");
+    provider.setCredentials(AuthScope.ANY, credentials);
+
+    httpClient = HttpClientBuilder.create()
+            .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
+            .setDefaultCredentialsProvider(provider)
+            .build();
   }
 
   @Override
diff --git a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
index 9035007..9ecf489 100644
--- a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
+++ b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
@@ -73,7 +73,7 @@
   }
 
   public String getInfraManagerConfDir() {
-    return ambariFolder + "/ambari-infra/ambari-infra-manager/ambari-infra-manager/target/package/conf";
+    return ambariFolder + "/ambari-infra/ambari-infra-manager/target/package/conf";
   }
 
   @BeforeStories
diff --git a/ambari-infra-manager-it/src/test/resources/conf/infra-manager.properties b/ambari-infra-manager-it/src/test/resources/conf/infra-manager.properties
index bb75fad..586a0fa 100644
--- a/ambari-infra-manager-it/src/test/resources/conf/infra-manager.properties
+++ b/ambari-infra-manager-it/src/test/resources/conf/infra-manager.properties
@@ -17,9 +17,8 @@
 infra-manager.batch.db.init=false
 infra-manager.batch.db.username=admin
 infra-manager.batch.db.password=admin
-management.security.enabled=false
-management.health.solr.enabled=false
 infra-manager.server.data.folder=/tmp/ambariInfraManager
+infra-manager.admin-user.password=admin
 
 # Archive Service Logs
 infra-manager.jobs.solr_data_archiving.archive_service_logs.enabled=true
diff --git a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerConfig.java b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerConfig.java
index 86059a2..39fff7d 100644
--- a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerConfig.java
+++ b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerConfig.java
@@ -31,6 +31,8 @@
 
   @Bean
   public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
-    return new PropertySourcesPlaceholderConfigurer();
+    PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
+    propertySourcesPlaceholderConfigurer.setNullValue("@null");
+    return propertySourcesPlaceholderConfigurer;
   }
 }
diff --git a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerWebServerCustomizer.java b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerWebServerCustomizer.java
index e560ae9..9ed0861 100644
--- a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerWebServerCustomizer.java
+++ b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/InfraManagerWebServerCustomizer.java
@@ -23,6 +23,7 @@
 import java.time.Duration;
 
 import javax.inject.Inject;
+import javax.inject.Named;
 
 import org.apache.ambari.infra.conf.security.SslSecrets;
 import org.springframework.beans.factory.annotation.Value;
@@ -30,9 +31,8 @@
 import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
 import org.springframework.boot.web.server.Ssl;
 import org.springframework.boot.web.server.WebServerFactoryCustomizer;
-import org.springframework.stereotype.Component;
 
-@Component
+@Named
 public class InfraManagerWebServerCustomizer implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {
 
   @Value("${infra-manager.server.port:61890}")
diff --git a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/InfraManagerSecurityConfig.java b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/SecretStoreConfig.java
similarity index 97%
rename from ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/InfraManagerSecurityConfig.java
rename to ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/SecretStoreConfig.java
index 008dec5..72b64d5 100644
--- a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/InfraManagerSecurityConfig.java
+++ b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/SecretStoreConfig.java
@@ -25,7 +25,7 @@
 import org.springframework.context.annotation.Configuration;
 
 @Configuration
-public class InfraManagerSecurityConfig {
+public class SecretStoreConfig {
 
   @Value("${"+ CREDENTIAL_STORE_PROVIDER_PATH_PROPERTY + ":}")
   private String credentialStoreProviderPath;
diff --git a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/WebSecurityConfig.java b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/WebSecurityConfig.java
new file mode 100644
index 0000000..ef59ab1
--- /dev/null
+++ b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/security/WebSecurityConfig.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.ambari.infra.conf.security;
+
+import static java.util.Arrays.asList;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+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.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.OrRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+  @Value("${infra-manager.admin-user.username:admin}")
+  private String adminUserName;
+
+  @Value("${infra-manager.admin-user.password:@null}")
+  private String adminUserPassword;
+
+  @Override
+  protected void configure(HttpSecurity http) throws Exception {
+    http.csrf().disable().authorizeRequests()
+            .requestMatchers(publicEndpoints())
+            .permitAll()
+            .antMatchers("/**")
+            .hasRole("ADMIN")
+            .and()
+            .httpBasic();
+  }
+
+  private RequestMatcher publicEndpoints() {
+    return new OrRequestMatcher(asList(
+            new AntPathRequestMatcher("/docs/**"),
+            new AntPathRequestMatcher("/swagger-ui/**"),
+            new AntPathRequestMatcher("/api/v1/swagger.yaml")
+    ));
+  }
+
+  @Inject
+  public void configureGlobal(
+          AuthenticationManagerBuilder auth,
+          PasswordEncoder passwordEncoder,
+          HadoopCredentialStore hadoopCredentialStore) throws Exception {
+
+    Secret adminPassword = new CompositeSecret(
+            hadoopCredentialStore.getSecret("infra_manager_admin_user_password"),
+            () -> Optional.ofNullable(adminUserPassword));
+
+    auth.inMemoryAuthentication()
+            .passwordEncoder(passwordEncoder)
+            .withUser(adminUserName)
+            .password(passwordEncoder.encode(adminPassword.get().orElseThrow(() -> new IllegalStateException("Password for admin not set!"))))
+            .roles("ADMIN");
+  }
+
+  @Bean
+  public PasswordEncoder passwordEncoder() {
+    return new BCryptPasswordEncoder();
+  }
+}
\ No newline at end of file
diff --git a/ambari-infra-manager/src/main/resources/infra-manager.properties b/ambari-infra-manager/src/main/resources/infra-manager.properties
index 938cf02..8133905 100644
--- a/ambari-infra-manager/src/main/resources/infra-manager.properties
+++ b/ambari-infra-manager/src/main/resources/infra-manager.properties
@@ -17,8 +17,6 @@
 infra-manager.batch.db.init=false
 infra-manager.batch.db.username=admin
 infra-manager.batch.db.password=admin
-management.security.enabled=false
-management.health.solr.enabled=false
 infra-manager.server.data.folder=/tmp/ambariInfraManager
 
 # Archive Service Logs