<commit_before>/*
 * Copyright 2013 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
 *
 *      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.springframework.boot.actuate.autoconfigure;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.crsh.auth.AuthenticationPlugin;
import org.crsh.plugin.CRaSHPlugin;
import org.crsh.plugin.PluginContext;
import org.crsh.plugin.PluginDiscovery;
import org.crsh.plugin.PluginLifeCycle;
import org.crsh.plugin.PropertyDescriptor;
import org.crsh.plugin.ServiceLoaderDiscovery;
import org.crsh.vfs.FS;
import org.crsh.vfs.spi.AbstractFSDriver;
import org.crsh.vfs.spi.FSDriver;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.ShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.JaasAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.KeyAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.SimpleAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.SpringAuthenticationProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.SpringVersion;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * {@link EnableAutoConfiguration Auto-configuration} for embedding an extensible shell
 * into a Spring Boot enabled application. By default a SSH daemon is started on port
 * 2000. If the CRaSH Telnet plugin is available on the classpath, Telnet deamon will be
 * launched on port 5000.
 * 
 * <p>
 * The default shell authentication method uses a username and password combination. If no
 * configuration is provided the default username is 'user' and the password will be
 * printed to console during application startup. Those default values can be overridden
 * by using <code>shell.auth.simple.username</code> and
 * <code>shell.auth.simple.password</code>.
 * 
 * <p>
 * If a Spring Security {@link AuthenticationManager} is detected, this configuration will
 * create a {@link CRaSHPlugin} to forward shell authentication requests to Spring
 * Security. This authentication method will get enabled if <code>shell.auth</code> is set
 * to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
 * {@link AuthenticationManager} is available. In the latter case shell access will be
 * restricted to users having roles that match those configured in
 * {@link ManagementServerProperties}. Required roles can be overridden by
 * <code>shell.auth.spring.roles</code>.
 * 
 * <p>
 * To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
 * the application context. Those beans will get auto detected during startup and
 * registered with the underlying shell infrastructure. To configure plugins and the CRaSH
 * infrastructure add beans of type {@link CrshShellProperties} to the application
 * context.
 * 
 * <p>
 * Additional shell commands can be implemented using the guide and documentation at <a
 * href="http://www.crashub.org">crashub.org</a>. By default Boot will search for commands
 * using the following classpath scanning pattern <code>classpath*:/commands/**</code>. To
 * add different locations or override the default use
 * <code>shell.command_path_patterns</code> in your application configuration.
 * 
 * @author <NAME>
 * @see ShellProperties
 */
@Configuration
@ConditionalOnClass({ PluginLifeCycle.class })
@EnableConfigurationProperties({ ShellProperties.class })
@AutoConfigureAfter(ManagementSecurityAutoConfiguration.class)
public class CrshAutoConfiguration {

	@Autowired
	private ShellProperties properties;

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'jaas'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties jaasAuthenticationProperties() {
		return new JaasAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'key'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties keyAuthenticationProperties() {
		return new KeyAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'simple'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties simpleAuthenticationProperties() {
		return new SimpleAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'spring'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties springAuthenticationProperties() {
		return new SpringAuthenticationProperties();
	}

	@Bean
	@ConditionalOnMissingBean({ PluginLifeCycle.class })
	public PluginLifeCycle shellBootstrap() {
		CrshBootstrapBean bootstrapBean = new CrshBootstrapBean();
		bootstrapBean.setConfig(this.properties.asCrshShellConfig());
		return bootstrapBean;
	}

	/**
	 * Class to configure CRaSH to authenticate against Spring Security.
	 */
	@Configuration
	@ConditionalOnBean({ AuthenticationManager.class })
	@AutoConfigureAfter(CrshAutoConfiguration.class)
	public static class AuthenticationManagerAdapterAutoConfiguration {

		@Autowired(required = false)
		private ManagementServerProperties management;

		@Bean
		public CRaSHPlugin<?> shellAuthenticationManager() {
			return new AuthenticationManagerAdapter();
		}

		@Bean
		@ConditionalOnExpression("'${shell.auth:default_spring}' == 'default_spring'")
		@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
		public CrshShellAuthenticationProperties springAuthenticationProperties() {
			// In case no shell.auth property is provided fall back to Spring Security
			// based authentication and get role to access shell from SecurityProperties.
			SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
			if (this.management != null) {
				authenticationProperties.setRoles(new String[] { this.management
						.getSecurity().getRole() });
			}
			return authenticationProperties;
		}

	}

	/**
	 * Spring Bean used to bootstrap the CRaSH shell.
	 */
	public static class CrshBootstrapBean extends PluginLifeCycle {

		@Autowired
		private ListableBeanFactory beanFactory;

		@Autowired
		private ShellProperties properties;

		@Autowired
		private ResourcePatternResolver resourceLoader;

		@PreDestroy
		public void destroy() {
			stop();<commit_msg>Pin order to of crsh auto configuration to happen after any security related configuration<commit_after>/*
 * Copyright 2013 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
 *
 *      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.springframework.boot.actuate.autoconfigure;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.crsh.auth.AuthenticationPlugin;
import org.crsh.plugin.CRaSHPlugin;
import org.crsh.plugin.PluginContext;
import org.crsh.plugin.PluginDiscovery;
import org.crsh.plugin.PluginLifeCycle;
import org.crsh.plugin.PropertyDescriptor;
import org.crsh.plugin.ServiceLoaderDiscovery;
import org.crsh.vfs.FS;
import org.crsh.vfs.spi.AbstractFSDriver;
import org.crsh.vfs.spi.FSDriver;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.ShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
import org.springframework.boot.actuate.properties.ShellProperties.JaasAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.KeyAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.SimpleAuthenticationProperties;
import org.springframework.boot.actuate.properties.ShellProperties.SpringAuthenticationProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.SpringVersion;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * {@link EnableAutoConfiguration Auto-configuration} for embedding an extensible shell
 * into a Spring Boot enabled application. By default a SSH daemon is started on port
 * 2000. If the CRaSH Telnet plugin is available on the classpath, Telnet deamon will be
 * launched on port 5000.
 * 
 * <p>
 * The default shell authentication method uses a username and password combination. If no
 * configuration is provided the default username is 'user' and the password will be
 * printed to console during application startup. Those default values can be overridden
 * by using <code>shell.auth.simple.username</code> and
 * <code>shell.auth.simple.password</code>.
 * 
 * <p>
 * If a Spring Security {@link AuthenticationManager} is detected, this configuration will
 * create a {@link CRaSHPlugin} to forward shell authentication requests to Spring
 * Security. This authentication method will get enabled if <code>shell.auth</code> is set
 * to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
 * {@link AuthenticationManager} is available. In the latter case shell access will be
 * restricted to users having roles that match those configured in
 * {@link ManagementServerProperties}. Required roles can be overridden by
 * <code>shell.auth.spring.roles</code>.
 * 
 * <p>
 * To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
 * the application context. Those beans will get auto detected during startup and
 * registered with the underlying shell infrastructure. To configure plugins and the CRaSH
 * infrastructure add beans of type {@link CrshShellProperties} to the application
 * context.
 * 
 * <p>
 * Additional shell commands can be implemented using the guide and documentation at <a
 * href="http://www.crashub.org">crashub.org</a>. By default Boot will search for commands
 * using the following classpath scanning pattern <code>classpath*:/commands/**</code>. To
 * add different locations or override the default use
 * <code>shell.command_path_patterns</code> in your application configuration.
 * 
 * @author <NAME>
 * @see ShellProperties
 */
@Configuration
@ConditionalOnClass({ PluginLifeCycle.class })
@EnableConfigurationProperties({ ShellProperties.class })
@AutoConfigureAfter({ SecurityAutoConfiguration.class,
		ManagementSecurityAutoConfiguration.class })
public class CrshAutoConfiguration {

	@Autowired
	private ShellProperties properties;

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'jaas'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties jaasAuthenticationProperties() {
		return new JaasAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'key'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties keyAuthenticationProperties() {
		return new KeyAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'simple'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties simpleAuthenticationProperties() {
		return new SimpleAuthenticationProperties();
	}

	@Bean
	@ConditionalOnExpression("'${shell.auth:simple}' == 'spring'")
	@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
	public CrshShellAuthenticationProperties springAuthenticationProperties() {
		return new SpringAuthenticationProperties();
	}

	@Bean
	@ConditionalOnMissingBean({ PluginLifeCycle.class })
	public PluginLifeCycle shellBootstrap() {
		CrshBootstrapBean bootstrapBean = new CrshBootstrapBean();
		bootstrapBean.setConfig(this.properties.asCrshShellConfig());
		return bootstrapBean;
	}

	/**
	 * Class to configure CRaSH to authenticate against Spring Security.
	 */
	@Configuration
	@ConditionalOnBean({ AuthenticationManager.class })
	@AutoConfigureAfter(CrshAutoConfiguration.class)
	public static class AuthenticationManagerAdapterAutoConfiguration {

		@Autowired(required = false)
		private ManagementServerProperties management;

		@Bean
		public CRaSHPlugin<?> shellAuthenticationManager() {
			return new AuthenticationManagerAdapter();
		}

		@Bean
		@ConditionalOnExpression("'${shell.auth:default_spring}' == 'default_spring'")
		@ConditionalOnMissingBean({ CrshShellAuthenticationProperties.class })
		public CrshShellAuthenticationProperties springAuthenticationProperties() {
			// In case no shell.auth property is provided fall back to Spring Security
			// based authentication and get role to access shell from
			// ManagementServerProperties.
			SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
			if (this.management != null) {
				authenticationProperties.setRoles(new String[] { this.management
						.getSecurity().getRole() });
			}
			return authenticationProperties;
		}

	}

	/**
	 * Spring Bean used to bootstrap the CRaSH shell.
	 */
	public static class CrshBootstrapBean extends PluginLifeCycle {

		@Autowired
		private ListableBeanFactory beanFactory;

		@Autowired
		private ShellProperties properties;

		@Autowired
		private ResourcePatternResolver resourceLoader;

		@PreDestroy
		public void destroy() {
			stop();
{'fraction_non_alphanumeric': 0.08439141856392295, 'fraction_numerical': 0.0017513134851138354, 'mean_word_length': 6.179960707269156, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4363223', 'n_tokens_mistral': 4688, 'n_tokens_neox': 4512, 'n_words': 1284}