Browse Source

AMBARI-25485: Change authentication method from get to post (#3540)

Yu Hou 3 years ago
parent
commit
86d9f77ca1

+ 49 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/AuthResourceDefinition.java

@@ -0,0 +1,49 @@
+/*
+ * 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.server.api.resources;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Auth Resource Definition
+ */
+public class AuthResourceDefinition extends BaseResourceDefinition {
+
+  public AuthResourceDefinition() {
+    super(Resource.Type.Auth);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "auths";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "auth";
+  }
+
+  @Override
+  public Set<SubResourceDefinition> getSubResourceDefinitions() {
+    return Collections.emptySet();
+  }
+
+}

+ 4 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java

@@ -485,6 +485,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new RemoteClusterResourceDefinition();
         break;
 
+      case Auth:
+        resourceDefinition = new AuthResourceDefinition();
+        break;
+
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);
     }

+ 85 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/users/AuthService.java

@@ -0,0 +1,85 @@
+/*
+ * 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.server.api.services.users;
+
+import java.util.Collections;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.http.HttpStatus;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * Service responsible for auth requests.
+ */
+@Path("/auth")
+@Api(value = "Auth", description = "Endpoint for authentication operations")
+public class AuthService extends BaseService {
+
+  private static final String AUTH_USERS_REQUEST_TYPE = "org.apache.ambari.server.controller.AuthRequestCreateAuthSwagger";
+
+  /**
+   * Is used as auth request.
+   * Handles: POST /auth
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return information regarding the requested user and related info
+   */
+  @POST
+  @Produces("text/plain")
+  @ApiOperation(value = "User authorization request")
+  @ApiImplicitParams({
+          @ApiImplicitParam(dataType = AUTH_USERS_REQUEST_TYPE, paramType = PARAM_TYPE_BODY, allowMultiple = true)
+  })
+  @ApiResponses({
+          @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+          @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+          @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+          @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response getUsersViaPost(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, body, ui, Request.Type.POST, createAuthResource());
+  }
+
+  /**
+   * Create an auth resource instance.
+   *
+   * @return an auth resource instance
+   */
+  private ResourceInstance createAuthResource() {
+    return createResource(Resource.Type.Auth, Collections.EMPTY_MAP);
+  }
+}

+ 27 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AuthRequestCreateAuthSwagger.java

@@ -0,0 +1,27 @@
+/*
+ * 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.server.controller;
+
+/**
+ * Interface to help correct Swagger documentation generation.
+ * Class is empty because not input/output fields are assumed.
+ */
+public interface AuthRequestCreateAuthSwagger extends ApiModel {
+
+}

+ 2 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java

@@ -64,6 +64,7 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
+import org.apache.ambari.server.controller.internal.AuthResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.CredentialResourceProvider;
@@ -498,6 +499,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("alertTarget"), AlertTargetResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("viewInstance"), ViewInstanceResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("rootServiceHostComponentConfiguration"), RootServiceComponentConfigurationResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("auth"), AuthResourceProvider.class)
         .build(ResourceProviderFactory.class));
 
     install(new FactoryModuleBuilder().implement(

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java

@@ -47,6 +47,9 @@ public interface ResourceProviderFactory {
   @Named("user")
   ResourceProvider getUserResourceProvider(AmbariManagementController managementController);
 
+  @Named("auth")
+  ResourceProvider getAuthResourceProvider(AmbariManagementController managementController);
+
   @Named("userAuthenticationSource")
   ResourceProvider getUserAuthenticationSourceResourceProvider();
 

+ 2 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java

@@ -247,6 +247,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return resourceProviderFactory.getAlertTargetResourceProvider();
       case ViewInstance:
         return resourceProviderFactory.getViewInstanceResourceProvider();
+      case Auth:
+        return resourceProviderFactory.getAuthResourceProvider(managementController);
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

+ 80 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AuthResourceProvider.java

@@ -0,0 +1,80 @@
+/*
+ * 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.server.controller.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.ResourcePredicateEvaluator;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+
+/**
+ * Resource provider for auth resources.
+ */
+public class AuthResourceProvider extends AbstractControllerResourceProvider implements ResourcePredicateEvaluator {
+
+  /**
+   * Create a new resource provider for the given management controller.
+   */
+  @AssistedInject
+  AuthResourceProvider(@Assisted AmbariManagementController managementController) {
+    super(Resource.Type.Auth, Collections.emptySet(), Collections.emptyMap(), managementController);
+  }
+
+  @Override
+  public RequestStatus createResourcesAuthorized(Request request)
+      throws SystemException,
+      UnsupportedPropertyException,
+      ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    // do nothing
+    return getRequestStatus(null);
+  }
+
+  /**
+   * ResourcePredicateEvaluator implementation. If property type is Auth/user_name,
+   * we do a case insensitive comparison so that we can return the retrieved
+   * username when it differs only in case with respect to the requested username.
+   *
+   * @param predicate the predicate
+   * @param resource  the resource
+   * @return
+   */
+  @Override
+  public boolean evaluate(Predicate predicate, Resource resource) {
+    return true;
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return new HashSet<>();
+  }
+}

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java

@@ -163,7 +163,8 @@ public interface Resource {
     VersionDefinition,
     ClusterKerberosDescriptor,
     LoggingQuery,
-    RemoteCluster;
+    RemoteCluster,
+    Auth;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -288,6 +289,7 @@ public interface Resource {
     public static final Type ClusterKerberosDescriptor = InternalType.ClusterKerberosDescriptor.getType();
     public static final Type LoggingQuery = InternalType.LoggingQuery.getType();
     public static final Type RemoteCluster = InternalType.RemoteCluster.getType();
+    public static final Type Auth = InternalType.Auth.getType();
 
 
     /**

+ 5 - 0
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java

@@ -75,6 +75,7 @@ public class AmbariAuthorizationFilter implements Filter {
   private static final String API_WIDGET_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/widgets.*";
   private static final String API_CLUSTERS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters.*";
   private static final String API_VIEWS_ALL_PATTERN = API_VERSION_PREFIX + "/views.*";
+  private static final String API_AUTH_PATTERN = API_VERSION_PREFIX + "/auth";
   private static final String API_PERSIST_ALL_PATTERN = API_VERSION_PREFIX + "/persist.*";
   private static final String API_LDAP_SYNC_EVENTS_ALL_PATTERN = API_VERSION_PREFIX + "/ldap_sync_events.*";
   private static final String API_CREDENTIALS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/credentials.*";
@@ -250,6 +251,10 @@ public class AmbariAuthorizationFilter implements Filter {
                 authorized = true;
                 break;
               }
+            } else if (requestURI.matches(API_AUTH_PATTERN) && "POST".equalsIgnoreCase(httpRequest.getMethod())) {
+              // all are able to login
+              authorized = true;
+              break;
             }
           }
         }