mneethiraj commented on code in PR #928: URL: https://github.com/apache/ranger/pull/928#discussion_r3158494904
########## authz-remote/src/conf/ranger-authz-remote.properties: ########## @@ -0,0 +1,31 @@ +# 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. + +ranger.authorizer.impl.class=org.apache.ranger.authz.remote.RangerRemoteAuthorizer +ranger.authz.remote.pdp.url=http://localhost:6500 +ranger.authz.remote.pdp.connect.timeout.ms=5000 +ranger.authz.remote.pdp.read.timeout.ms=30000 + +# ranger.authz.remote.auth.type=kerberos|jwt Review Comment: `none` is a valid value as well, right?? ########## ranger-examples/sample-client/src/main/resources/ranger-authz-remote-authn-jwt.properties: ########## @@ -0,0 +1,30 @@ +# +# 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. +# +ranger.authorizer.impl.class=org.apache.ranger.authz.remote.RangerRemoteAuthorizer +ranger.authz.remote.pdp.url=http://localhost:6500 +ranger.authz.remote.pdp.connect.timeout.ms=5000 +ranger.authz.remote.pdp.read.timeout.ms=30000 + +# ranger.authz.remote.auth.type=kerberos|jwt Review Comment: Since this files is specifically for jwt authn, I suggest removing all other authn properties. ########## ranger-examples/sample-client/src/main/resources/ranger-authz-remote-authn-kerberos.properties: ########## @@ -0,0 +1,30 @@ +# +# 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. +# +ranger.authorizer.impl.class=org.apache.ranger.authz.remote.RangerRemoteAuthorizer +ranger.authz.remote.pdp.url=http://localhost:6500 +ranger.authz.remote.pdp.connect.timeout.ms=5000 +ranger.authz.remote.pdp.read.timeout.ms=30000 + +# ranger.authz.remote.auth.type=kerberos|jwt +ranger.authz.remote.authn.type=kerberos +ranger.authz.remote.authn.kerberos.principal= +ranger.authz.remote.authn.kerberos.keytab= + +# ranger.authz.remote.authn.jwt.source=env|file|cred Review Comment: Since this file is specifically for kerberos authn, I suggest removing other authn properties. ########## authz-remote/src/main/java/org/apache/ranger/authz/remote/RangerPdpClient.java: ########## @@ -0,0 +1,278 @@ +/* + * 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.ranger.authz.remote; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.util.EntityUtils; +import org.apache.ranger.authz.api.RangerAuthzException; +import org.apache.ranger.authz.model.RangerAuthzRequest; +import org.apache.ranger.authz.model.RangerAuthzResult; +import org.apache.ranger.authz.model.RangerMultiAuthzRequest; +import org.apache.ranger.authz.model.RangerMultiAuthzResult; +import org.apache.ranger.authz.model.RangerResourcePermissions; +import org.apache.ranger.authz.model.RangerResourcePermissionsRequest; +import org.apache.ranger.authz.remote.authn.RangerRemoteJwtProvider; +import org.apache.ranger.authz.remote.authn.RangerRemoteKerberosContext; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + +import java.io.Closeable; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Map; + +import static org.apache.ranger.authz.remote.RangerRemoteAuthType.JWT; +import static org.apache.ranger.authz.remote.RangerRemoteAuthType.KERBEROS; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.FAILED_TO_DESERIALIZE_RESPONSE; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.FAILED_TO_SERIALIZE_REQUEST; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.REMOTE_CALL_UNSUCCESSFUL; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.REMOTE_REQUEST_FAILED; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.TLS_CONFIGURATION_FAILED; + +class RangerPdpClient implements Closeable { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + private static final String PATH_AUTHORIZE = "/authorize"; + private static final String PATH_AUTHORIZE_MULTI = "/authorizeMulti"; + private static final String PATH_RESOURCE_PERMISSIONS = "/permissions"; + private static final String HEADER_AUTHORIZATION = "Authorization"; Review Comment: Move authentication type details (like `HEADER_AUTHORIZATION`, `JWT_HEADER_PREFIX`) to authN provider implementation class, and call a method like `authnProvider.setAuthNHeader(request)` from here. ########## ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/pdpclient/RemoteAuthzClient.java: ########## @@ -0,0 +1,160 @@ +/* + * 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.ranger.examples.pdpclient; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.authz.api.RangerAuthorizer; +import org.apache.ranger.authz.api.RangerAuthorizerFactory; +import org.apache.ranger.authz.model.RangerAccessContext; +import org.apache.ranger.authz.model.RangerAccessInfo; +import org.apache.ranger.authz.model.RangerAuthzRequest; +import org.apache.ranger.authz.model.RangerAuthzResult; +import org.apache.ranger.authz.model.RangerResourceInfo; +import org.apache.ranger.authz.model.RangerUserInfo; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Set; + +public final class RemoteAuthzClient { + private static final String DEFAULT_PROPERTIES_RESOURCE = "/tmp/ranger-authz-remote-test.properties"; + + private static final String PROP_TEST_REQUEST_ID = "ranger.authz.remote.test.requestId"; + private static final String PROP_TEST_EXPECT_DECISION = "ranger.authz.remote.test.expect.decision"; + private static final String PROP_TEST_USER_NAME = "ranger.authz.remote.test.user.name"; + private static final String PROP_TEST_USER_GROUPS = "ranger.authz.remote.test.user.groups"; + private static final String PROP_TEST_USER_ROLES = "ranger.authz.remote.test.user.roles"; + private static final String PROP_TEST_ACCESS_ACTION = "ranger.authz.remote.test.access.action"; + private static final String PROP_TEST_ACCESS_PERMISSIONS = "ranger.authz.remote.test.access.permissions"; + private static final String PROP_TEST_RESOURCE_NAME = "ranger.authz.remote.test.resource.name"; + private static final String PROP_TEST_RESOURCE_SUBRESOURCES = "ranger.authz.remote.test.resource.subResources"; + private static final String PROP_TEST_CONTEXT_SERVICE_TYPE = "ranger.authz.remote.test.context.serviceType"; + private static final String PROP_TEST_CONTEXT_SERVICE_NAME = "ranger.authz.remote.test.context.serviceName"; + private static final String PROP_TEST_CONTEXT_CLIENT_IP = "ranger.authz.remote.test.context.clientIpAddress"; + + private RemoteAuthzClient() { + } + + public static void main(String[] args) throws Exception { + String propertiesLocation = args != null && args.length > 0 ? args[0] : "classpath:" + DEFAULT_PROPERTIES_RESOURCE; + Properties properties = loadProperties(propertiesLocation); + + System.out.println("Loaded properties from: " + propertiesLocation); + + RangerAuthzResult result = run(properties); + + System.out.println("Decision: " + result.getDecision()); + System.out.println("Result : " + result); + + String expectedDecision = StringUtils.trimToNull(properties.getProperty(PROP_TEST_EXPECT_DECISION)); + + if (expectedDecision != null && !expectedDecision.equalsIgnoreCase(String.valueOf(result.getDecision()))) { + throw new IllegalStateException("Expected decision " + expectedDecision + " but got " + result.getDecision()); + } + } + + static RangerAuthzResult run(Properties properties) throws Exception { + RangerAuthorizer authorizer = RangerAuthorizerFactory.createAuthorizer(properties); + + try { + authorizer.init(); + + RangerAuthzRequest request = buildRequest(properties); + + System.out.println("Request : " + request); + + return authorizer.authorize(request); + } finally { + authorizer.close(); + } + } + + static Properties loadProperties(String location) throws Exception { + Properties properties = new Properties(); + + try (InputStream input = openInputStream(location)) { + properties.load(input); + } + + return properties; + } + + private static InputStream openInputStream(String location) throws Exception { + String effectiveLocation = StringUtils.defaultIfBlank(location, "classpath:" + DEFAULT_PROPERTIES_RESOURCE); Review Comment: Defaulting to `DEFAULT_PROPERTIES_RESOURCE` is already done by the caller, at line 59. Remove the duplicate code from here. ########## authz-remote/src/main/java/org/apache/ranger/authz/remote/authn/RangerRemoteJwtProvider.java: ########## @@ -0,0 +1,122 @@ +/* + * 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.ranger.authz.remote.authn; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.authz.api.RangerAuthzException; +import org.apache.ranger.authz.remote.RangerRemoteAuthzConfig; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.INVALID_PROPERTY_VALUE; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.MISSING_AUTH_CONFIG; +import static org.apache.ranger.authz.remote.RangerRemoteAuthzErrorCode.REMOTE_REQUEST_FAILED; + +public class RangerRemoteJwtProvider { + private static final String SOURCE_ENV = "env"; + private static final String SOURCE_FILE = "file"; + + private final String source; + private final String envVar; + private final String filePath; + + private long fileLastModified; + private volatile String jwt; + + private RangerRemoteJwtProvider(String source, String envVar, String filePath) { + this.source = source; + this.envVar = envVar; + this.filePath = filePath; + } + + public static RangerRemoteJwtProvider create(RangerRemoteAuthzConfig config) throws RangerAuthzException { + String source = config.getJwtSource().trim().toLowerCase(); + + switch (source) { + case SOURCE_ENV: + return new RangerRemoteJwtProvider(source, config.getJwtEnvVar(), null); + + case SOURCE_FILE: + return new RangerRemoteJwtProvider(source, null, config.getJwtFile()); + + default: + throw new RangerAuthzException(INVALID_PROPERTY_VALUE, RangerRemoteAuthzConfig.PROP_REMOTE_AUTH_JWT_SOURCE, source); + } + } + + public String getJwt() throws RangerAuthzException { + switch (source) { + case SOURCE_ENV: + jwt = System.getenv(envVar); + break; + + case SOURCE_FILE: + refreshJwtFromFile(); + break; + + default: + throw new RangerAuthzException(INVALID_PROPERTY_VALUE, RangerRemoteAuthzConfig.PROP_REMOTE_AUTH_JWT_SOURCE, source); + } + + if (StringUtils.isBlank(jwt)) { + throw new RangerAuthzException(MISSING_AUTH_CONFIG, getSourcePropertyName()); + } + + return jwt.trim(); Review Comment: `jwt` could be null in following cases: - env variable is not found - file is not present or not readable In such cases, avoid NPE by checking for null and raising an exception. ########## ranger-examples/sample-client/src/main/resources/ranger-authz-remote-authn-jwt.properties: ########## @@ -0,0 +1,30 @@ +# +# 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. +# +ranger.authorizer.impl.class=org.apache.ranger.authz.remote.RangerRemoteAuthorizer +ranger.authz.remote.pdp.url=http://localhost:6500 +ranger.authz.remote.pdp.connect.timeout.ms=5000 +ranger.authz.remote.pdp.read.timeout.ms=30000 + +# ranger.authz.remote.auth.type=kerberos|jwt +ranger.authz.remote.authn.type=jwt +ranger.authz.remote.authn.kerberos.principal= +ranger.authz.remote.authn.kerberos.keytab= + +# ranger.authz.remote.authn.jwt.source=env|file|cred Review Comment: `cred` is not a valid value. ########## ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/pdpclient/RemoteAuthzClient.java: ########## @@ -0,0 +1,160 @@ +/* + * 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.ranger.examples.pdpclient; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.authz.api.RangerAuthorizer; +import org.apache.ranger.authz.api.RangerAuthorizerFactory; +import org.apache.ranger.authz.model.RangerAccessContext; +import org.apache.ranger.authz.model.RangerAccessInfo; +import org.apache.ranger.authz.model.RangerAuthzRequest; +import org.apache.ranger.authz.model.RangerAuthzResult; +import org.apache.ranger.authz.model.RangerResourceInfo; +import org.apache.ranger.authz.model.RangerUserInfo; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Set; + +public final class RemoteAuthzClient { + private static final String DEFAULT_PROPERTIES_RESOURCE = "/tmp/ranger-authz-remote-test.properties"; Review Comment: Instead of `/tmp/`, I suggest to load either from current directory or classpath. ########## ranger-examples/sample-client/src/main/java/org/apache/ranger/examples/pdpclient/RemoteAuthzClient.java: ########## @@ -0,0 +1,160 @@ +/* + * 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.ranger.examples.pdpclient; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.authz.api.RangerAuthorizer; +import org.apache.ranger.authz.api.RangerAuthorizerFactory; +import org.apache.ranger.authz.model.RangerAccessContext; +import org.apache.ranger.authz.model.RangerAccessInfo; +import org.apache.ranger.authz.model.RangerAuthzRequest; +import org.apache.ranger.authz.model.RangerAuthzResult; +import org.apache.ranger.authz.model.RangerResourceInfo; +import org.apache.ranger.authz.model.RangerUserInfo; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Properties; +import java.util.Set; + +public final class RemoteAuthzClient { + private static final String DEFAULT_PROPERTIES_RESOURCE = "/tmp/ranger-authz-remote-test.properties"; + + private static final String PROP_TEST_REQUEST_ID = "ranger.authz.remote.test.requestId"; + private static final String PROP_TEST_EXPECT_DECISION = "ranger.authz.remote.test.expect.decision"; + private static final String PROP_TEST_USER_NAME = "ranger.authz.remote.test.user.name"; + private static final String PROP_TEST_USER_GROUPS = "ranger.authz.remote.test.user.groups"; + private static final String PROP_TEST_USER_ROLES = "ranger.authz.remote.test.user.roles"; + private static final String PROP_TEST_ACCESS_ACTION = "ranger.authz.remote.test.access.action"; + private static final String PROP_TEST_ACCESS_PERMISSIONS = "ranger.authz.remote.test.access.permissions"; + private static final String PROP_TEST_RESOURCE_NAME = "ranger.authz.remote.test.resource.name"; + private static final String PROP_TEST_RESOURCE_SUBRESOURCES = "ranger.authz.remote.test.resource.subResources"; + private static final String PROP_TEST_CONTEXT_SERVICE_TYPE = "ranger.authz.remote.test.context.serviceType"; + private static final String PROP_TEST_CONTEXT_SERVICE_NAME = "ranger.authz.remote.test.context.serviceName"; + private static final String PROP_TEST_CONTEXT_CLIENT_IP = "ranger.authz.remote.test.context.clientIpAddress"; + + private RemoteAuthzClient() { + } + + public static void main(String[] args) throws Exception { + String propertiesLocation = args != null && args.length > 0 ? args[0] : "classpath:" + DEFAULT_PROPERTIES_RESOURCE; + Properties properties = loadProperties(propertiesLocation); + + System.out.println("Loaded properties from: " + propertiesLocation); + + RangerAuthzResult result = run(properties); Review Comment: Instead of reading request details from properties file, I suggest reading request.json file location as a command-line argument. And simply print the result, instead of validating for an expected result. ``` if (args == null || args.length < 1) { // throw exception with appropriate usage message } String requestJson = readFile(args[0]); String properties = loadProperties(args.length > 1 ? args[1] : DEFAULT_PROPERTIES_RESOURCE); RangerAuthorizer authorizer = RangerAuthorizerFactory.createAuthorizer(properties); authorizer.init(); RangerAuthzRequest request = OBJECT_MAPPER.readValue(requestJson, RangerAuthzRequest.class); RangerAuthzResult result = authorizer.authorize(request); System.println(OBJECT_MAPPER.writeValue(result)); ... ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
