Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
import org.opensearch.security.configuration.DlsFlsValveImpl;
import org.opensearch.security.configuration.SecurityConfigVersionHandler;
import org.opensearch.security.configuration.SecurityFlsDlsIndexSearcherWrapper;
import org.opensearch.security.configuration.SuperAdminAuthority;
import org.opensearch.security.dlic.rest.api.Endpoint;
import org.opensearch.security.dlic.rest.api.SecurityRestApiActions;
import org.opensearch.security.dlic.rest.api.ssl.CertificatesActionType;
Expand Down Expand Up @@ -287,6 +288,7 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin
private volatile AtomicReference<DiscoveryNode> localNode = new AtomicReference<>();
private volatile AuditLog auditLog;
private volatile BackendRegistry backendRegistry;
private volatile SuperAdminAuthority superAdminAuthority;
private volatile SslExceptionHandler sslExceptionHandler;
private volatile Client localClient;
private final boolean disabled;
Expand Down Expand Up @@ -683,7 +685,7 @@ public List<RestHandler> getRestHandlers(
Objects.requireNonNull(privilegesConfiguration),
Objects.requireNonNull(threadPool),
Objects.requireNonNull(cs),
Objects.requireNonNull(adminDns),
Objects.requireNonNull(superAdminAuthority),
Objects.requireNonNull(cr)
)
);
Expand All @@ -692,7 +694,7 @@ public List<RestHandler> getRestHandlers(
settings,
restController,
Objects.requireNonNull(threadPool),
adminDns,
Objects.requireNonNull(superAdminAuthority),
configPath,
principalExtractor
)
Expand All @@ -702,7 +704,7 @@ public List<RestHandler> getRestHandlers(
settings,
restController,
Objects.requireNonNull(threadPool),
adminDns,
Objects.requireNonNull(superAdminAuthority),
configPath,
principalExtractor
)
Expand All @@ -714,7 +716,7 @@ public List<RestHandler> getRestHandlers(
configPath,
restController,
localClient,
adminDns,
Objects.requireNonNull(superAdminAuthority),
cr,
cs,
principalExtractor,
Expand Down Expand Up @@ -759,7 +761,7 @@ public UnaryOperator<RestHandler> getRestHandlerWrapper(final ThreadContext thre
return (rh) -> rh;
}

return (rh) -> securityRestHandler.wrap(rh, adminDns, headersToCopy);
return (rh) -> securityRestHandler.wrap(rh, superAdminAuthority, headersToCopy);
}

@Override
Expand Down Expand Up @@ -793,7 +795,7 @@ public void onIndexModule(IndexModule indexModule) {
indexService -> new SecurityFlsDlsIndexSearcherWrapper(
indexService,
settings,
adminDns,
superAdminAuthority,
cs,
auditLog,
ciol,
Expand Down Expand Up @@ -1222,7 +1224,8 @@ public Collection<Object> createComponents(
userService = new UserService(cs, cr, passwordHasher, settings, localClient);

final XFFResolver xffResolver = new XFFResolver(threadPool);
backendRegistry = new BackendRegistry(settings, adminDns, xffResolver, auditLog, threadPool, cih);
superAdminAuthority = new SuperAdminAuthority(adminDns, settings, threadPool);
backendRegistry = new BackendRegistry(settings, superAdminAuthority, xffResolver, auditLog, threadPool, cih);
backendRegistry.registerClusterSettingsChangeListener(clusterService.getClusterSettings());
cr.subscribeOnChange(configMap -> { backendRegistry.invalidateCache(); });

Expand Down Expand Up @@ -1255,7 +1258,7 @@ public Collection<Object> createComponents(
);
this.privilegesConfiguration = privilegesConfiguration;

dlsFlsBaseContext = new DlsFlsBaseContext(privilegesConfiguration, threadPool.getThreadContext(), adminDns);
dlsFlsBaseContext = new DlsFlsBaseContext(privilegesConfiguration, threadPool.getThreadContext(), superAdminAuthority);

if (SSLConfig.isSslOnlyMode()) {
dlsFlsValve = new DlsFlsRequestValve.NoopDlsFlsRequestValve();
Expand All @@ -1267,13 +1270,13 @@ public Collection<Object> createComponents(
xContentRegistry,
threadPool,
dlsFlsBaseContext,
adminDns,
superAdminAuthority,
resourcePluginInfo,
resourceSharingEnabledSetting
);
}

resourceAccessHandler = new ResourceAccessHandler(threadPool, rsIndexHandler, adminDns, resourcePluginInfo);
resourceAccessHandler = new ResourceAccessHandler(threadPool, rsIndexHandler, superAdminAuthority, resourcePluginInfo);

// Assign resource sharing client to each extension
// Using the non-gated client (i.e. no additional permissions required)
Expand All @@ -1299,7 +1302,7 @@ public Collection<Object> createComponents(
sf = new SecurityFilter(
settings,
privilegesConfiguration,
adminDns,
superAdminAuthority,
dlsFlsValve,
auditLog,
threadPool,
Expand Down Expand Up @@ -1372,6 +1375,7 @@ public Collection<Object> createComponents(
components.add(cr);
components.add(xffResolver);
components.add(backendRegistry);
components.add(superAdminAuthority);
components.add(auditLog);
components.add(privilegesConfiguration);
components.add(restLayerEvaluator);
Expand Down Expand Up @@ -2333,6 +2337,8 @@ public List<Setting<?>> getSettings() {

settings.add(SecuritySettings.USER_ATTRIBUTE_SERIALIZATION_ENABLED_SETTING);
settings.add(SecuritySettings.DLS_WRITE_BLOCKED);
settings.add(SecuritySettings.SECURITY_SUPERADMIN_SECRET_SETTING);
settings.add(SecuritySettings.SECURITY_SUPERADMIN_SECRET_INSECURE_SETTING);
}

return settings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ public void logFailedLogin(String effectiveUser, boolean securityadmin, String i
msg.addRestRequestInfo(request, auditConfigFilter);
msg.addInitiatingUser(initiatingUser);
msg.addEffectiveUser(effectiveUser);
msg.addIsAdminDn(securityadmin);
msg.addIsAdminDn(isDnAdmin(securityadmin, request));
msg.addIsSuperadminSecret(isSecretAdmin(securityadmin, request));

save(msg);
}
Expand All @@ -183,7 +184,9 @@ public void logSucceededLogin(String effectiveUser, boolean securityadmin, Strin
msg.addRestRequestInfo(request, auditConfigFilter);
msg.addInitiatingUser(initiatingUser);
msg.addEffectiveUser(effectiveUser);
msg.addIsAdminDn(securityadmin);
msg.addIsAdminDn(isDnAdmin(securityadmin, request));
msg.addIsSuperadminSecret(isSecretAdmin(securityadmin, request));

save(msg);
}

Expand Down Expand Up @@ -1031,4 +1034,12 @@ public void onDynamicConfigModelChanged(DynamicConfigModel dcm) {
ignoredUrlParams.addAll(authDomain.getHttpAuthenticator().getSensitiveUrlParams());
}
}

private boolean isDnAdmin(boolean securityadmin, SecurityRequest request) {
return (securityadmin && request.header(ConfigConstants.SECURITY_SUPERADMIN_SECRET_HEADER) == null);
}

private boolean isSecretAdmin(boolean securityadmin, SecurityRequest request) {
return (securityadmin && request.header(ConfigConstants.SECURITY_SUPERADMIN_SECRET_HEADER) != null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public final class AuditMessage {

public static final String EXCEPTION = "audit_request_exception_stacktrace";
public static final String IS_ADMIN_DN = "audit_request_effective_user_is_admin";
public static final String IS_SUPERADMIN_SECRET = "audit_request_effective_user_is_superadmin_secret";
public static final String PRIVILEGE = "audit_request_privilege";

public static final String TASK_ID = "audit_trace_task_id";
Expand Down Expand Up @@ -174,6 +175,10 @@ public void addIsAdminDn(boolean isAdminDn) {
auditInfo.put(IS_ADMIN_DN, isAdminDn);
}

public void addIsSuperadminSecret(boolean isSuperadminSecret) {
auditInfo.put(IS_SUPERADMIN_SECRET, isSuperadminSecret);
}

public void addException(Throwable t) {
if (t != null) {
auditInfo.put(EXCEPTION, ExceptionsHelper.stackTrace(t));
Expand Down
45 changes: 30 additions & 15 deletions src/main/java/org/opensearch/security/auth/BackendRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.opensearch.security.auth.internal.NoOpAuthenticationBackend;
import org.opensearch.security.configuration.AdminDNs;
import org.opensearch.security.configuration.ClusterInfoHolder;
import org.opensearch.security.configuration.SuperAdminAuthority;
import org.opensearch.security.filter.GrpcRequestChannel;
import org.opensearch.security.filter.SecurityRequest;
import org.opensearch.security.filter.SecurityRequestChannel;
Expand Down Expand Up @@ -101,6 +102,7 @@ public class BackendRegistry {
private volatile boolean initialized;
private volatile boolean injectedUserEnabled = false;
private final AdminDNs adminDns;
private final SuperAdminAuthority superAdminAuthority;
private final XFFResolver xffResolver;
private volatile boolean anonymousAuthEnabled = false;
private final Settings opensearchSettings;
Expand Down Expand Up @@ -156,13 +158,14 @@ public void registerClusterSettingsChangeListener(final ClusterSettings clusterS

public BackendRegistry(
final Settings settings,
final AdminDNs adminDns,
final SuperAdminAuthority superAdminAuthority,
final XFFResolver xffResolver,
final AuditLog auditLog,
final ThreadPool threadPool,
final ClusterInfoHolder clusterInfoHolder
) {
this.adminDns = adminDns;
this.superAdminAuthority = superAdminAuthority;
this.adminDns = superAdminAuthority.getAdminDns();
this.opensearchSettings = settings;
this.xffResolver = xffResolver;
this.auditLog = auditLog;
Expand Down Expand Up @@ -262,20 +265,32 @@ public boolean authenticate(final SecurityRequestChannel request) {
}

/*
Authenticates superuser based on client certificate auth. The certificate DN is read from thread context and
compared against adminDNs. If superuser is authenticated here we skip the remaining authentication flow.
Note that non superuser client/cert authentication is handled separately by the HTTPClientCertAuthenticator
auth backend.
Authenticates superadmin based on either certificate or superadmin secret.
Uses SuperAdminAuthority to coordinate authentication methods.
If superadmin is authenticated here, skip the remaining auth flow.
*/
ThreadContext threadContext = this.threadPool.getThreadContext();
final String sslPrincipal = (String) threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PRINCIPAL);
if (adminDns.isAdminDN(sslPrincipal)) {
// PKI authenticated REST call
User superuser = new User(sslPrincipal);
UserSubject subject = new UserSubjectImpl(threadPool, superuser);
threadContext.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, subject);
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, superuser);
return true;
if (!gRPC && superAdminAuthority.isRequestFromSuperAdmin(request)) {
// Determine which type of superadmin authentication succeeded
ThreadContext threadContext = this.threadPool.getThreadContext();
final String sslPrincipal = (String) threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PRINCIPAL);
if (adminDns.isAdminDN(sslPrincipal)) {
// Certificate-based admin
User superuser = new User(sslPrincipal);
UserSubject subject = new UserSubjectImpl(threadPool, superuser);
threadContext.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, subject);
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, superuser);
return true;
} else {
// Secret-based superadmin
User superuser = new User(superAdminAuthority.getSuperadminSecretUserName());
UserSubject subject = new UserSubjectImpl(threadPool, superuser);
threadContext.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, subject);
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, superuser);
return true;
}
} else if (!gRPC && superAdminAuthority.hasSecretHeader(request)) {
// Failed superadmin secret authentication attempt
auditLog.logFailedLogin("superadmin", true, null, request);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public class DlsFlsValveImpl implements DlsFlsRequestValve {
private final DlsFlsBaseContext dlsFlsBaseContext;
private final FieldMasking.Config fieldMaskingConfig;
private final Settings settings;
private final AdminDNs adminDNs;
private final SuperAdminAuthority superAdminAuthority;
private final OpensearchDynamicSetting<Boolean> resourceSharingEnabledSetting;
private final ResourcePluginInfo resourcePluginInfo;
private volatile boolean dlsWriteBlockedEnabled;
Expand All @@ -118,7 +118,7 @@ public DlsFlsValveImpl(
NamedXContentRegistry namedXContentRegistry,
ThreadPool threadPool,
DlsFlsBaseContext dlsFlsBaseContext,
AdminDNs adminDNs,
SuperAdminAuthority superAdminAuthority,
ResourcePluginInfo resourcePluginInfo,
OpensearchDynamicSetting<Boolean> resourceSharingEnabledSetting
) {
Expand All @@ -131,7 +131,7 @@ public DlsFlsValveImpl(
this.fieldMaskingConfig = FieldMasking.Config.fromSettings(settings);
this.dlsFlsBaseContext = dlsFlsBaseContext;
this.settings = settings;
this.adminDNs = adminDNs;
this.superAdminAuthority = superAdminAuthority;
this.resourcePluginInfo = resourcePluginInfo;

clusterService.addListener(event -> {
Expand Down Expand Up @@ -171,7 +171,7 @@ public boolean invoke(PrivilegesEvaluationContext context, final ActionListener<
}

UserSubjectImpl userSubject = (UserSubjectImpl) threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER);
if (userSubject != null && adminDNs.isAdmin(userSubject.getUser())) {
if (userSubject != null && superAdminAuthority.isSuperAdmin(userSubject.getUser())) {
return true;
}
OptionallyResolvedIndices resolved = context.getResolvedIndices();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class SecurityFlsDlsIndexSearcherWrapper extends SystemIndexSearcherWrapp
public SecurityFlsDlsIndexSearcherWrapper(
final IndexService indexService,
final Settings settings,
final AdminDNs adminDNs,
final SuperAdminAuthority superAdminAuthority,
final ClusterService clusterService,
final AuditLog auditlog,
final ComplianceIndexingOperationListener ciol,
Expand All @@ -75,7 +75,7 @@ public SecurityFlsDlsIndexSearcherWrapper(
final Supplier<DlsFlsProcessedConfig> dlsFlsProcessedConfigSupplier,
final DlsFlsBaseContext dlsFlsBaseContext
) {
super(indexService, settings, adminDNs, privilegesConfiguration, roleMapper);
super(indexService, settings, superAdminAuthority, privilegesConfiguration, roleMapper);
Set<String> metadataFieldsCopy;
if (indexService.getMetadata().getState() == IndexMetadata.State.CLOSE) {
if (log.isDebugEnabled()) {
Expand Down
Loading
Loading