Search in sources :

Example 1 with Credential

use of io.cdap.cdap.proto.security.Credential in project cdap by caskdata.

the class AuthenticationHandler method channelRead.

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (!(msg instanceof HttpRequest)) {
        ctx.fireChannelRead(msg);
        return;
    }
    HttpRequest request = (HttpRequest) msg;
    // Pass if security is bypassed or it has valid access token, process to the next handler
    if (isBypassed(request)) {
        ctx.fireChannelRead(msg);
        return;
    }
    UserIdentityExtractionResponse extractionResponse = userIdentityExtractor.extract(request);
    if (extractionResponse.success()) {
        UserIdentityPair userIdentityPair = extractionResponse.getIdentityPair();
        // User identity extraction succeeded, so set some header properties and allow the call through
        request.headers().remove(HttpHeaderNames.AUTHORIZATION);
        Credential credential = getUserCredential(userIdentityPair);
        // For backwards compatibility, we continue propagating credentials by default. This may change in the future.
        if (cConf.getBoolean(Constants.Security.Authentication.PROPAGATE_USER_CREDENTIAL, true) && credential != null) {
            request.headers().set(Constants.Security.Headers.RUNTIME_TOKEN, String.format("%s %s", credential.getType().getQualifiedName(), credential.getValue()));
        }
        request.headers().set(Constants.Security.Headers.USER_ID, userIdentityPair.getUserIdentity().getUsername());
        String clientIP = Networks.getIP(ctx.channel().remoteAddress());
        if (clientIP != null) {
            request.headers().set(Constants.Security.Headers.USER_IP, clientIP);
        }
        ctx.fireChannelRead(msg);
        return;
    }
    // Response with failure, plus optionally audit log
    try {
        HttpHeaders headers = new DefaultHttpHeaders();
        JsonObject jsonObject = new JsonObject();
        if (extractionResponse.getState().equals(UserIdentityExtractionState.ERROR_MISSING_CREDENTIAL)) {
            headers.add(HttpHeaderNames.WWW_AUTHENTICATE, String.format("Bearer realm=\"%s\"", realm));
            LOG.debug("Authentication failed due to missing credentials");
        } else {
            String shortError = extractionResponse.getState().toString();
            String errorDescription = extractionResponse.getErrorDescription();
            headers.add(HttpHeaderNames.WWW_AUTHENTICATE, String.format("Bearer realm=\"%s\" error=\"%s\" error_description=\"%s\"", realm, shortError, errorDescription));
            jsonObject.addProperty("error", shortError);
            jsonObject.addProperty("error_description", errorDescription);
            LOG.debug("Authentication failed due to error {}, reason={};", shortError, errorDescription);
        }
        jsonObject.add("auth_uri", getAuthenticationURLs());
        ByteBuf content = Unpooled.copiedBuffer(jsonObject.toString(), StandardCharsets.UTF_8);
        HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED, content);
        HttpUtil.setContentLength(response, content.readableBytes());
        HttpUtil.setKeepAlive(response, false);
        response.headers().setAll(headers);
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=UTF-8");
        auditLogIfNeeded(request, response, ctx.channel());
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    } finally {
        ReferenceCountUtil.release(msg);
    }
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) Credential(io.cdap.cdap.proto.security.Credential) UserIdentityExtractionResponse(io.cdap.cdap.security.auth.UserIdentityExtractionResponse) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) JsonObject(com.google.gson.JsonObject) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) HttpResponse(io.netty.handler.codec.http.HttpResponse) UserIdentityPair(io.cdap.cdap.security.auth.UserIdentityPair) ByteBuf(io.netty.buffer.ByteBuf)

Example 2 with Credential

use of io.cdap.cdap.proto.security.Credential in project cdap by caskdata.

the class AuthenticationHandler method getUserCredential.

/**
 * Get user credential from {@link UserIdentityPair} and return it in encrypted form if enabled.
 */
@Nullable
private Credential getUserCredential(UserIdentityPair userIdentityPair) throws CipherException {
    String userCredential = userIdentityPair.getUserCredential();
    if (userCredential == null || !sConf.getBoolean(Constants.Security.Authentication.USER_CREDENTIAL_ENCRYPTION_ENABLED, false)) {
        return new Credential(userCredential, Credential.CredentialType.EXTERNAL);
    }
    String encryptedCredential = new TinkCipher(sConf).encryptStringToBase64(userCredential, null);
    return new Credential(encryptedCredential, Credential.CredentialType.EXTERNAL_ENCRYPTED);
}
Also used : Credential(io.cdap.cdap.proto.security.Credential) TinkCipher(io.cdap.cdap.security.auth.TinkCipher) Nullable(javax.annotation.Nullable)

Example 3 with Credential

use of io.cdap.cdap.proto.security.Credential in project cdap by caskdata.

the class RemoteClient method setHeader.

private Multimap<String, String> setHeader(HttpRequest request) throws IOException {
    Multimap<String, String> headers = request.getHeaders();
    headers = headers == null ? HashMultimap.create() : HashMultimap.create(headers);
    // Add Authorization header and use a rewritten URL if needed
    if (remoteAuthenticator != null && headers.keySet().stream().noneMatch(HttpHeaders.AUTHORIZATION::equalsIgnoreCase)) {
        Credential credential = remoteAuthenticator.getCredentials();
        if (credential != null) {
            setAuthHeader(headers::put, HttpHeaders.AUTHORIZATION, credential.getType().getQualifiedName(), credential.getValue());
        }
    }
    internalAuthenticator.applyInternalAuthenticationHeaders(headers::put);
    return headers;
}
Also used : HttpHeaders(com.google.common.net.HttpHeaders) Credential(io.cdap.cdap.proto.security.Credential)

Example 4 with Credential

use of io.cdap.cdap.proto.security.Credential in project cdap by caskdata.

the class AuthenticationChannelHandler method channelRead.

/**
 * Decode the AccessTokenIdentifier passed as a header and set it in a ThreadLocal.
 * Returns a 401 if the identifier is malformed.
 */
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    SecurityRequestContext.reset();
    // is fixed since we may perform auth checks in the thread processing the last chunk.
    if (msg instanceof HttpRequest) {
        String currentUserID = null;
        Credential currentUserCredential = null;
        String currentUserIP = null;
        if (internalAuthEnabled) {
            // When internal auth is enabled, all requests should typically have user id and credential
            // associated with them, for instance, end user credential for user originated ones and
            // internal system credential for system originated requests. If there is none, set
            // default empty user id and credential.
            currentUserID = EMPTY_USER_ID;
            currentUserCredential = EMPTY_USER_CREDENTIAL;
            currentUserIP = EMPTY_USER_IP;
        }
        // TODO: authenticate the user using user id - CDAP-688
        HttpRequest request = (HttpRequest) msg;
        String userID = request.headers().get(Constants.Security.Headers.USER_ID);
        if (userID != null) {
            currentUserID = userID;
        }
        String userIP = request.headers().get(Constants.Security.Headers.USER_IP);
        if (userIP != null) {
            currentUserIP = userIP;
        }
        String authHeader = request.headers().get(Constants.Security.Headers.RUNTIME_TOKEN);
        if (authHeader != null) {
            int idx = authHeader.trim().indexOf(' ');
            if (idx < 0) {
                LOG.error("Invalid Authorization header format for {}@{}", currentUserID, currentUserIP);
                if (internalAuthEnabled) {
                    throw new IllegalArgumentException("Invalid Authorization header format");
                }
            } else {
                String credentialTypeStr = authHeader.substring(0, idx);
                try {
                    Credential.CredentialType credentialType = Credential.CredentialType.fromQualifiedName(credentialTypeStr);
                    String credentialValue = authHeader.substring(idx + 1).trim();
                    currentUserCredential = new Credential(credentialValue, credentialType);
                    SecurityRequestContext.setUserCredential(currentUserCredential);
                } catch (IllegalArgumentException e) {
                    LOG.error("Invalid credential type in Authorization header: {}", credentialTypeStr);
                    throw e;
                }
            }
        }
        LOG.trace("Got user ID '{}' user IP '{}' from IP '{}' and authorization header length '{}'", userID, userIP, ctx.channel().remoteAddress(), authHeader == null ? "NULL" : authHeader.length());
        SecurityRequestContext.setUserId(currentUserID);
        SecurityRequestContext.setUserCredential(currentUserCredential);
        SecurityRequestContext.setUserIP(currentUserIP);
    }
    try {
        ctx.fireChannelRead(msg);
    } finally {
        SecurityRequestContext.reset();
    }
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) Credential(io.cdap.cdap.proto.security.Credential)

Example 5 with Credential

use of io.cdap.cdap.proto.security.Credential in project cdap by caskdata.

the class DefaultPreviewRequestQueueTest method testPreviewRequestQueue.

@Test
public void testPreviewRequestQueue() {
    PreviewConfig previewConfig = new PreviewConfig("WordCount", ProgramType.WORKFLOW, null, null);
    AppRequest<?> testRequest = new AppRequest<>(new ArtifactSummary("test", "1.0"), null, previewConfig);
    byte[] pollerInfo = Bytes.toBytes("runner-1");
    Optional<PreviewRequest> requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertFalse(requestOptional.isPresent());
    ApplicationId app1 = new ApplicationId("default", RunIds.generate().getId());
    PreviewRequest request = new PreviewRequest(app1, testRequest, null);
    previewRequestQueue.add(request);
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertTrue(requestOptional.isPresent());
    request = requestOptional.get();
    ProgramId programId1 = new ProgramId(app1, ProgramType.WORKFLOW, "WordCount");
    Assert.assertEquals(programId1, request.getProgram());
    Principal principal = new Principal("userFoo", Principal.PrincipalType.USER, new Credential("userFooCredential", Credential.CredentialType.EXTERNAL));
    PreviewRequest requestWithPrinciple = new PreviewRequest(app1, testRequest, principal);
    previewRequestQueue.add(requestWithPrinciple);
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertTrue(requestOptional.isPresent());
    request = requestOptional.get();
    Assert.assertTrue(request.getPrincipal().equals(principal));
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertFalse(requestOptional.isPresent());
    ApplicationId app2 = new ApplicationId("default", RunIds.generate().getId());
    request = new PreviewRequest(app2, testRequest, null);
    previewRequestQueue.add(request);
    Assert.assertEquals(0, previewRequestQueue.positionOf(app2));
    ApplicationId app3 = new ApplicationId("default", RunIds.generate().getId());
    request = new PreviewRequest(app3, testRequest, null);
    previewRequestQueue.add(request);
    Assert.assertEquals(1, previewRequestQueue.positionOf(app3));
    ApplicationId app4 = new ApplicationId("default", RunIds.generate().getId());
    request = new PreviewRequest(app4, testRequest, null);
    boolean exceptionThrown = false;
    try {
        previewRequestQueue.add(request);
    } catch (IllegalStateException e) {
        exceptionThrown = true;
    }
    Assert.assertTrue(exceptionThrown);
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertTrue(requestOptional.isPresent());
    request = requestOptional.get();
    ProgramId programId2 = new ProgramId(app2, ProgramType.WORKFLOW, "WordCount");
    Assert.assertEquals(programId2, request.getProgram());
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertTrue(requestOptional.isPresent());
    request = requestOptional.get();
    ProgramId programId3 = new ProgramId(app3, ProgramType.WORKFLOW, "WordCount");
    Assert.assertEquals(programId3, request.getProgram());
    requestOptional = previewRequestQueue.poll(pollerInfo);
    Assert.assertFalse(requestOptional.isPresent());
}
Also used : Credential(io.cdap.cdap.proto.security.Credential) ProgramId(io.cdap.cdap.proto.id.ProgramId) AppRequest(io.cdap.cdap.proto.artifact.AppRequest) ArtifactSummary(io.cdap.cdap.api.artifact.ArtifactSummary) PreviewRequest(io.cdap.cdap.app.preview.PreviewRequest) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) PreviewConfig(io.cdap.cdap.proto.artifact.preview.PreviewConfig) Principal(io.cdap.cdap.proto.security.Principal) Test(org.junit.Test)

Aggregations

Credential (io.cdap.cdap.proto.security.Credential)38 Principal (io.cdap.cdap.proto.security.Principal)29 Test (org.junit.Test)25 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)16 UserIdentity (io.cdap.cdap.security.auth.UserIdentity)13 EntityId (io.cdap.cdap.proto.id.EntityId)6 AccessController (io.cdap.cdap.security.spi.authorization.AccessController)5 NoOpAccessController (io.cdap.cdap.security.spi.authorization.NoOpAccessController)5 TinkCipher (io.cdap.cdap.security.auth.TinkCipher)4 CConfiguration (io.cdap.cdap.common.conf.CConfiguration)3 SConfiguration (io.cdap.cdap.common.conf.SConfiguration)3 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)3 IOException (java.io.IOException)3 HttpURLConnection (java.net.HttpURLConnection)3 ArtifactSummary (io.cdap.cdap.api.artifact.ArtifactSummary)2 PreviewRequest (io.cdap.cdap.app.preview.PreviewRequest)2 RemoteClient (io.cdap.cdap.common.internal.remote.RemoteClient)2 RemoteClientFactory (io.cdap.cdap.common.internal.remote.RemoteClientFactory)2 AppRequest (io.cdap.cdap.proto.artifact.AppRequest)2 PreviewConfig (io.cdap.cdap.proto.artifact.preview.PreviewConfig)2