diff --git a/geode-spring-boot-starter/src/main/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxy.java b/geode-spring-boot-starter/src/main/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxy.java
new file mode 100644
index 00000000..2e346be8
--- /dev/null
+++ b/geode-spring-boot-starter/src/main/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxy.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2018 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.data.geode.security.support;
+
+import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
+
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.geode.security.AuthenticationFailedException;
+import org.apache.geode.security.ResourcePermission;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.gemfire.support.LazyWiringDeclarableSupport;
+import org.springframework.util.Assert;
+
+/**
+ * The {@link SecurityManagerProxy} class is an Apache Geode {@link org.apache.geode.security.SecurityManager}
+ * proxy implementation delegating to a backing {@link org.apache.geode.security.SecurityManager} implementation
+ * which is registered as a managed bean in a Spring context.
+ *
+ * The idea behind this {@link org.apache.geode.security.SecurityManager} is to enable users to be able to configure
+ * and manage the {@code SecurityManager} as a Spring bean. However, Apache Geode/Pivotal GemFire require
+ * the {@link org.apache.geode.security.SecurityManager} to be configured using a System property when launching
+ * Apache Geode Servers with Gfsh, which makes it difficult to "manage" the {@code SecurityManager} instance.
+ *
+ * Therefore, this implementation allows a developer to set the Apache Geode System property using this proxy...
+ *
+ *
+ * gemfire.security-manager=org.springframework.boot.data.geode.security.support.SecurityManagerProxy
+ *
+ *
+ * And then declare and define a bean in the Spring context implementing the
+ * {@link org.apache.geode.security.SecurityManager} interface...
+ *
+ *
+ * @Configuration
+ * class MyApplicationConfiguration {
+ *
+ * @Bean
+ * ExampleSecurityManager exampleSecurityManager(Environment environment) {
+ * return new ExampleSecurityManager(environment);
+ * }
+ *
+ * ...
+ * }
+ *
+ *
+ * @author John Blum
+ * @see org.apache.geode.security.SecurityManager
+ * @see org.springframework.data.gemfire.support.LazyWiringDeclarableSupport
+ * @since 1.0.0
+ */
+@SuppressWarnings("unused")
+public class SecurityManagerProxy extends LazyWiringDeclarableSupport
+ implements org.apache.geode.security.SecurityManager {
+
+ private static final AtomicReference INSTANCE = new AtomicReference<>();
+
+ private org.apache.geode.security.SecurityManager securityManager;
+
+ /**
+ * Returns a reference to the single {@link SecurityManagerProxy} instance configured by
+ * Apache Geode/Pivotal GemFire in startup.
+ *
+ * @return a reference to the single {@link SecurityManagerProxy} instance.
+ */
+ public static SecurityManagerProxy getInstance() {
+
+ return Optional.ofNullable(INSTANCE.get())
+ .orElseThrow(() -> newIllegalStateException("SecurityManagerProxy was not configured"));
+ }
+
+
+ /**
+ * Constructs a new instance of {@link SecurityManagerProxy}, which will delegate all Apache Geode
+ * security operations to a Spring managed {@link org.apache.geode.security.SecurityManager} bean.
+ */
+ public SecurityManagerProxy() {
+
+ // TODO remove init() call when GEODE-2083 (https://issues.apache.org/jira/browse/GEODE-2083) is resolved!
+ // NOTE: the init(:Properties) call in the constructor is less than ideal since...
+ // 1) it allows the *this* reference to escape, and...
+ // 2) it is Geode's responsibility to identify Geode Declarable objects and invoke their init(:Properties) method
+ // However, the init(:Properties) method invocation in the constructor is necessary to enable this Proxy to be
+ // identified and auto-wired in a Spring context.
+
+ INSTANCE.compareAndSet(null, this);
+ init(new Properties());
+ }
+
+ /**
+ * Configures a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
+ * delegated to by this {@link SecurityManagerProxy}.
+ *
+ * @param securityManager reference to the underlying Apache Geode {@link org.apache.geode.security.SecurityManager}
+ * instance delegated to by this {@link SecurityManagerProxy}.
+ * @throws IllegalArgumentException if the {@link org.apache.geode.security.SecurityManager} reference
+ * is {@literal null}.
+ * @see org.apache.geode.security.SecurityManager
+ */
+ @Autowired
+ public void setSecurityManager(org.apache.geode.security.SecurityManager securityManager) {
+
+ Assert.notNull(securityManager, "SecurityManager must not be null");
+
+ this.securityManager = securityManager;
+ }
+
+ /**
+ * Returns a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
+ * delegated to by this {@link SecurityManagerProxy}.
+ *
+ * @return a reference to the underlying {@link org.apache.geode.security.SecurityManager} instance
+ * delegated to by this {@link SecurityManagerProxy}.
+ * @throws IllegalStateException if the configured {@link org.apache.geode.security.SecurityManager}
+ * was not properly configured.
+ * @see org.apache.geode.security.SecurityManager
+ */
+ protected org.apache.geode.security.SecurityManager getSecurityManager() {
+
+ Assert.state(this.securityManager != null, "No SecurityManager configured");
+
+ return this.securityManager;
+ }
+
+ @Override
+ public Object authenticate(Properties properties) throws AuthenticationFailedException {
+ return getSecurityManager().authenticate(properties);
+ }
+
+ @Override
+ public boolean authorize(Object principal, ResourcePermission permission) {
+ return getSecurityManager().authorize(principal, permission);
+ }
+
+ @Override
+ public void close() {
+ getSecurityManager().close();
+ }
+}
diff --git a/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyIntegrationTests.java b/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyIntegrationTests.java
new file mode 100644
index 00000000..54b1c97a
--- /dev/null
+++ b/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyIntegrationTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 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.data.geode.security.support;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.apache.geode.cache.GemFireCache;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.gemfire.config.annotation.EnableSecurity;
+import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * Integration tests for {@link SecurityManagerProxy}.
+ *
+ * @author John Blum
+ * @see org.apache.geode.cache.GemFireCache
+ * @see org.apache.geode.security.SecurityManager
+ * @see org.springframework.context.annotation.Bean
+ * @see org.springframework.data.gemfire.config.annotation.EnableSecurity
+ * @see org.springframework.data.gemfire.config.annotation.PeerCacheApplication
+ * @see org.springframework.test.context.ContextConfiguration
+ * @see org.springframework.test.context.junit4.SpringRunner
+ * @since 1.0.0
+ */
+@RunWith(SpringRunner.class)
+@ContextConfiguration
+@SuppressWarnings("unused")
+public class SecurityManagerProxyIntegrationTests {
+
+ private static final String GEMFIRE_LOG_LEVEL = "error";
+
+ @Autowired
+ private org.apache.geode.security.SecurityManager mockSecurityManager;
+
+ @Test
+ public void securityManagerProxyWasConfiguredWithMockSecurityManager() {
+ assertThat(SecurityManagerProxy.getInstance().getSecurityManager()).isEqualTo(this.mockSecurityManager);
+ }
+
+ @PeerCacheApplication(logLevel = GEMFIRE_LOG_LEVEL, useBeanFactoryLocator = true)
+ @EnableSecurity(securityManagerClassName =
+ "org.springframework.boot.data.geode.security.support.SecurityManagerProxy")
+ static class TestConfiguration {
+
+ @Bean
+ org.apache.geode.security.SecurityManager mockSecurityManager(GemFireCache gemfireCache) {
+ return mock(org.apache.geode.security.SecurityManager.class);
+ }
+ }
+}
diff --git a/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyUnitTests.java b/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyUnitTests.java
new file mode 100644
index 00000000..93e18cea
--- /dev/null
+++ b/geode-spring-boot-starter/src/test/java/org/springframework/boot/data/geode/security/support/SecurityManagerProxyUnitTests.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2018 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.data.geode.security.support;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.security.Principal;
+import java.util.Properties;
+
+import org.apache.geode.security.ResourcePermission;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link SecurityManagerProxy}
+ *
+ * @author John Blum
+ * @see java.security.Principal
+ * @see org.junit.Test
+ * @see org.mockito.Mockito
+ * @see org.springframework.boot.data.geode.security.support.SecurityManagerProxy
+ * @since 1.0.0
+ */
+public class SecurityManagerProxyUnitTests {
+
+ @Test
+ public void setAndGetSecurityManager() {
+
+ org.apache.geode.security.SecurityManager mockSecurityManager =
+ mock(org.apache.geode.security.SecurityManager.class);
+
+ SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
+
+ securityManagerProxy.setSecurityManager(mockSecurityManager);
+
+ assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setSecurityManagerToNullThrowsIllegalArgumentException() {
+
+ try {
+ new SecurityManagerProxy().setSecurityManager(null);
+ }
+ catch (IllegalArgumentException expected) {
+
+ assertThat(expected).hasMessage("SecurityManager must not be null");
+ assertThat(expected).hasNoCause();
+
+ throw expected;
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void getSecurityManagerWhenUninitializedThrowsIllegalStateException() {
+
+ try {
+ new SecurityManagerProxy().getSecurityManager();
+ }
+ catch (IllegalStateException expected) {
+
+ assertThat(expected).hasMessage("No SecurityManager configured");
+ assertThat(expected).hasNoCause();
+
+ throw expected;
+ }
+ }
+
+ @Test
+ public void authenticateDelegatesToConfiguredSecurityManager() {
+
+ Properties securityProperties = new Properties();
+
+ org.apache.geode.security.SecurityManager mockSecurityManager =
+ mock(org.apache.geode.security.SecurityManager.class);
+
+ when(mockSecurityManager.authenticate(any(Properties.class))).thenReturn("TestUser");
+
+ SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
+
+ securityManagerProxy.setSecurityManager(mockSecurityManager);
+
+ assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
+ assertThat(securityManagerProxy.authenticate(securityProperties)).isEqualTo("TestUser");
+
+ verify(mockSecurityManager, times(1)).authenticate(eq(securityProperties));
+ }
+
+ @Test
+ public void authorizeDelegatesToConfiguredSecurityManager() {
+
+ Principal mockPrincipal = mock(Principal.class);
+
+ ResourcePermission resourcePermission =
+ new ResourcePermission(ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ);
+
+ org.apache.geode.security.SecurityManager mockSecurityManager =
+ mock(org.apache.geode.security.SecurityManager.class);
+
+ when(mockSecurityManager.authorize(any(Object.class), any(ResourcePermission.class))).thenReturn(true);
+
+ SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
+
+ securityManagerProxy.setSecurityManager(mockSecurityManager);
+
+ assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
+ assertThat(securityManagerProxy.authorize(mockPrincipal, resourcePermission)).isTrue();
+
+ verify(mockSecurityManager, times(1))
+ .authorize(eq(mockPrincipal), eq(resourcePermission));
+ }
+
+ @Test
+ public void closeDelegatesToConfiguredSecurityManager() {
+
+ org.apache.geode.security.SecurityManager mockSecurityManager =
+ mock(org.apache.geode.security.SecurityManager.class);
+
+ when(mockSecurityManager.authorize(any(Object.class), any(ResourcePermission.class))).thenReturn(true);
+
+ SecurityManagerProxy securityManagerProxy = new SecurityManagerProxy();
+
+ securityManagerProxy.setSecurityManager(mockSecurityManager);
+
+ assertThat(securityManagerProxy.getSecurityManager()).isEqualTo(mockSecurityManager);
+
+ securityManagerProxy.close();
+
+ verify(mockSecurityManager, times(1)).close();
+ }
+}