You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2016/04/29 22:32:18 UTC

[05/13] nifi git commit: NIFI-1554: - Populating component entities in the REST API to decouple key fields from the configuration DTOs. - Added initial support for components in UI when access isn't allowed. Formal styling to come later.

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java
index 16b55ee..3bc22f7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java
@@ -18,9 +18,10 @@ package org.apache.nifi.web;
 
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.cluster.context.ClusterContext;
 import org.apache.nifi.cluster.context.ClusterContextThreadLocal;
-import org.apache.nifi.web.security.user.NiFiUserUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
index 931f682..97a90d3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
@@ -78,6 +78,10 @@
             <artifactId>nifi-framework-core</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-framework-authorization</artifactId>
+        </dependency>
+        <dependency>
             <groupId>io.jsonwebtoken</groupId>
             <artifactId>jjwt</artifactId>
             <version>0.6.0</version>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
index 7108edb..817480f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java
@@ -25,8 +25,8 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.util.NiFiProperties;
-import org.apache.nifi.web.security.user.NiFiUserUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.authentication.AuthenticationManager;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
index 1b2f28a..605e98b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
@@ -23,7 +23,7 @@ import java.util.regex.Pattern;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java
index 3de5a2d..6c14ca5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java
@@ -16,9 +16,9 @@
  */
 package org.apache.nifi.web.security.anonymous;
 
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.Authentication;
@@ -41,6 +41,7 @@ public class NiFiAnonymousUserFilter extends AnonymousAuthenticationFilter {
 
     @Override
     protected Authentication createAuthentication(HttpServletRequest request) {
+        // TODO - conditional anonymous authentication
         return new NiFiAuthenticationToken(new NiFiUserDetails(NiFiUser.ANONYMOUS));
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java
index 289cc87..7634123 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java
@@ -17,10 +17,10 @@
 package org.apache.nifi.web.security.jwt;
 
 import io.jsonwebtoken.JwtException;
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.web.security.InvalidAuthenticationException;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
index 03e1400..8451c7c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
@@ -24,11 +24,12 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.controller.FlowController;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authentication.AuthenticationResponse;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
 import org.apache.nifi.web.security.x509.X509CertificateExtractor;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java
index 411efc1..8f2712c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java
@@ -16,10 +16,10 @@
  */
 package org.apache.nifi.web.security.otp;
 
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.web.security.InvalidAuthenticationException;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java
deleted file mode 100644
index 86668fe..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.nifi.web.security.user;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.user.NiFiUser;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * User details for a NiFi user.
- */
-public class NiFiUserDetails implements UserDetails {
-
-    private final NiFiUser user;
-
-    /**
-     * Creates a new NiFiUserDetails.
-     *
-     * @param user user
-     */
-    public NiFiUserDetails(NiFiUser user) {
-        this.user = user;
-    }
-
-    /**
-     * Get the user for this UserDetails.
-     *
-     * @return user
-     */
-    public NiFiUser getNiFiUser() {
-        return user;
-    }
-
-    /**
-     * Returns the authorities that this NiFi user has.
-     *
-     * @return authorities
-     */
-    @Override
-    public Collection<? extends GrantedAuthority> getAuthorities() {
-        return Collections.EMPTY_SET;
-    }
-
-    @Override
-    public String getPassword() {
-        return StringUtils.EMPTY;
-    }
-
-    @Override
-    public String getUsername() {
-        return user.getIdentity();
-    }
-
-    @Override
-    public boolean isAccountNonExpired() {
-        return true;
-    }
-
-    @Override
-    public boolean isAccountNonLocked() {
-        return true;
-    }
-
-    @Override
-    public boolean isCredentialsNonExpired() {
-        return true;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java
deleted file mode 100644
index 255b3d5..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.nifi.web.security.user;
-
-import java.util.HashSet;
-import java.util.Set;
-import org.apache.nifi.user.NiFiUser;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-
-/**
- * Utility methods for retrieving information about the current application user.
- *
- */
-public final class NiFiUserUtils {
-
-    /**
-     * Return the authorities for the current user.
-     *
-     * @return authorities
-     */
-    public static Set<String> getAuthorities() {
-        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
-
-        SecurityContext context = SecurityContextHolder.getContext();
-        if (context != null) {
-            Authentication authentication = context.getAuthentication();
-            if (authentication != null) {
-                // get the authorities for the user of the current request
-                grantedAuthorities.addAll(authentication.getAuthorities());
-            }
-        }
-
-        // convert to a list of authorities
-        Set<String> authorities = new HashSet<>(grantedAuthorities.size());
-        for (GrantedAuthority grantedAuthority : grantedAuthorities) {
-            authorities.add(grantedAuthority.getAuthority());
-        }
-
-        return authorities;
-    }
-
-    /**
-     * Returns the current NiFiUser or null if the current user is not a NiFiUser.
-     *
-     * @return user
-     */
-    public static NiFiUser getNiFiUser() {
-        NiFiUser user = null;
-
-        // obtain the principal in the current authentication
-        final SecurityContext context = SecurityContextHolder.getContext();
-        final Authentication authentication = context.getAuthentication();
-        if (authentication != null) {
-            Object principal = authentication.getPrincipal();
-            if (principal instanceof NiFiUserDetails) {
-                user = ((NiFiUserDetails) principal).getNiFiUser();
-            }
-        }
-
-        return user;
-    }
-
-    public static String getNiFiUserName() {
-        // get the nifi user to extract the username
-        NiFiUser user = NiFiUserUtils.getNiFiUser();
-        if (user == null) {
-            return "unknown";
-        } else {
-            return user.getUserName();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
index 2593f92..43d6958 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
@@ -18,11 +18,18 @@ package org.apache.nifi.web.security.x509;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authentication.AuthenticationResponse;
-import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.authorization.AuthorizationRequest;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.AuthorizationResult.Result;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.resource.ResourceFactory;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.web.security.InvalidAuthenticationException;
 import org.apache.nifi.web.security.ProxiedEntitiesUtils;
+import org.apache.nifi.web.security.UntrustedProxyException;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
@@ -37,9 +44,11 @@ import java.util.ListIterator;
 public class X509AuthenticationProvider implements AuthenticationProvider {
 
     private X509IdentityProvider certificateIdentityProvider;
+    private Authorizer authorizer;
 
-    public X509AuthenticationProvider(X509IdentityProvider certificateIdentityProvider) {
+    public X509AuthenticationProvider(final X509IdentityProvider certificateIdentityProvider, final Authorizer authorizer) {
         this.certificateIdentityProvider = certificateIdentityProvider;
+        this.authorizer = authorizer;
     }
 
     @Override
@@ -64,6 +73,24 @@ public class X509AuthenticationProvider implements AuthenticationProvider {
             // add the chain as appropriate to each proxy
             NiFiUser proxy = null;
             for (final ListIterator<String> chainIter = proxyChain.listIterator(proxyChain.size()); chainIter.hasPrevious();) {
+                final String identity = chainIter.previous();
+
+                if (chainIter.hasPrevious()) {
+                    // authorize this proxy in order to authenticate this user
+                    final AuthorizationRequest proxyAuthorizationRequest = new AuthorizationRequest.Builder()
+                        .identity(identity)
+                        .anonymous(false)
+                        .accessAttempt(true)
+                        .action(RequestAction.WRITE)
+                        .resource(ResourceFactory.getProxyResource())
+                        .build();
+
+                    final AuthorizationResult proxyAuthorizationResult = authorizer.authorize(proxyAuthorizationRequest);
+                    if (!Result.Approved.equals(proxyAuthorizationResult.getResult())) {
+                        throw new UntrustedProxyException(String.format("Untrusted proxy %s", identity));
+                    }
+                }
+
                 proxy = new NiFiUser(chainIter.previous(), proxy);
             }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml
index 12d8594..b4c3176 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml
@@ -41,7 +41,8 @@
 
     <!-- otp authentication provider -->
     <bean id="x509AuthenticationProvider" class="org.apache.nifi.web.security.x509.X509AuthenticationProvider">
-        <constructor-arg ref="certificateIdentityProvider"/>
+        <constructor-arg ref="certificateIdentityProvider" index="0"/>
+        <constructor-arg ref="authorizer" index="1"/>
     </bean>
 
     <!-- jwt service -->

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java
index a95c1a0..3fffad1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java
@@ -16,8 +16,8 @@
  */
 package org.apache.nifi.web.security.otp;
 
+import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.user.NiFiUserDetails;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js
index 6f27e41..1785ce3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js
@@ -38,15 +38,15 @@ nf.ng.BreadcrumbsCtrl = (function () {
             /**
              * Generate the breadcrumbs.
              *
-             * @param {object} processGroup  The process group used to generate breadcrumbs
+             * @param {object} breadcrumb  The breadcrumb
              */
-            generateBreadcrumbs: function (processGroup) {
+            generateBreadcrumbs: function (breadcrumb) {
                 //explicitly sanitize processGroup.name
-                processGroup.name = $sanitize(processGroup.name);
-                this.breadcrumbs.unshift(processGroup);
+                breadcrumb.name = $sanitize(breadcrumb.name);
+                this.breadcrumbs.unshift(breadcrumb);
 
-                if (nf.Common.isDefinedAndNotNull(processGroup.parent)) {
-                    this.generateBreadcrumbs(processGroup.parent);
+                if (nf.Common.isDefinedAndNotNull(breadcrumb.parentBreadcrumb)) {
+                    this.generateBreadcrumbs(breadcrumb.parentBreadcrumb);
                 }
             },
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index e950080..59f56fc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -87,23 +87,16 @@ nf.Actions = (function () {
 
     // create a method for updating process groups and processors
     var updateProcessGroup = function (response) {
-        if (nf.Common.isDefinedAndNotNull(response.processGroup)) {
-            if (nf.Common.isDefinedAndNotNull(response.processGroup.contents)) {
-                var contents = response.processGroup.contents;
-
-                // update all the components in the contents
-                nf.Graph.set(contents);
-
-                // update each process group
-                $.each(contents.processGroups, function (_, processGroup) {
-                    // reload the group's connections
-                    var connections = nf.Connection.getComponentConnections(processGroup.id);
-                    $.each(connections, function (_, connection) {
-                        nf.Connection.reload(connection);
-                    });
-                });
-            }
-        }
+        $.ajax({
+            type: 'GET',
+            url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(response.id),
+            data: {
+                verbose: true
+            },
+            dataType: 'json'
+        }).done(function (response) {
+            nf.Graph.set(response.processGroupFlow.flow);
+        });
     };
 
     return {
@@ -122,7 +115,7 @@ nf.Actions = (function () {
         enterGroup: function (selection) {
             if (selection.size() === 1 && nf.CanvasUtils.isProcessGroup(selection)) {
                 var selectionData = selection.datum();
-                nf.CanvasUtils.enterGroup(selectionData.component.id);
+                nf.CanvasUtils.enterGroup(selectionData.id);
             }
         },
         
@@ -168,7 +161,7 @@ nf.Actions = (function () {
                         if (refreshTimestamp === remoteProcessGroup.flowRefreshed) {
                             schedule(nextDelay);
                         } else {
-                            nf.RemoteProcessGroup.set(response.remoteProcessGroup);
+                            nf.RemoteProcessGroup.set(response);
 
                             // reload the group's connections
                             var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id);
@@ -372,7 +365,7 @@ nf.Actions = (function () {
                     };
                 } else {
                     var selectionData = selection.datum();
-                    var selectionPosition = selectionData.component.position;
+                    var selectionPosition = selectionData.position;
 
                     box = {
                         x: selectionPosition.x,
@@ -413,20 +406,15 @@ nf.Actions = (function () {
                     var selected = d3.select(this);
 
                     // build the entity
-                    var entity = {};
-                    entity[nf[d.type].getEntityKey(d)] = {
-                        'id': d.component.id,
-                        'state': 'STOPPED'
+                    var entity = {
+                        'component': {
+                            'id': d.id,
+                            'state': 'STOPPED'
+                        }
                     };
 
                     enableRequests.push(updateResource(d.component.uri, entity).done(function (response) {
-                        if (nf.CanvasUtils.isProcessor(selected)) {
-                            nf.Processor.set(response.processor);
-                        } else if (nf.CanvasUtils.isInputPort(selected)) {
-                            nf.Port.set(response.inputPort);
-                        } else if (nf.CanvasUtils.isOutputPort(selected)) {
-                            nf.Port.set(response.outputPort);
-                        }
+                        nf[d.type].set(response);
                     }));
                 });
 
@@ -460,20 +448,15 @@ nf.Actions = (function () {
                     var selected = d3.select(this);
 
                     // build the entity
-                    var entity = {};
-                    entity[nf[d.type].getEntityKey(d)] = {
-                        'id': d.component.id,
-                        'state': 'DISABLED'
+                    var entity = {
+                        'component': {
+                            'id': d.id,
+                            'state': 'DISABLED'
+                        }
                     };
 
                     disableRequests.push(updateResource(d.component.uri, entity).done(function (response) {
-                        if (nf.CanvasUtils.isProcessor(selected)) {
-                            nf.Processor.set(response.processor);
-                        } else if (nf.CanvasUtils.isInputPort(selected)) {
-                            nf.Port.set(response.inputPort);
-                        } else if (nf.CanvasUtils.isOutputPort(selected)) {
-                            nf.Port.set(response.outputPort);
-                        }
+                        nf[d.type].set(response);
                     }));
                 });
 
@@ -497,7 +480,7 @@ nf.Actions = (function () {
 
                 // open the provenance page with the specified component
                 nf.Shell.showPage('provenance?' + $.param({
-                    componentId: selectionData.component.id
+                    componentId: selectionData.id
                 }));
             }
         },
@@ -511,7 +494,7 @@ nf.Actions = (function () {
             if (selection.empty()) {
                 // build the entity
                 var entity = {
-                    'processGroup': {
+                    'component': {
                         'id': nf.Canvas.getGroupId(),
                         'running': true
                     }
@@ -538,7 +521,7 @@ nf.Actions = (function () {
 
                         // processor endpoint does not use running flag...
                         var component = {
-                            'id': d.component.id,
+                            'id': d.id,
                         };
                         if (nf.CanvasUtils.isProcessor(selected) || nf.CanvasUtils.isInputPort(selected) || nf.CanvasUtils.isOutputPort(selected)) {
                             component['state'] = 'RUNNING';
@@ -547,24 +530,21 @@ nf.Actions = (function () {
                         }
 
                         // build the entity
-                        var entity = {};
-                        entity[nf[d.type].getEntityKey(d)] = component;
+                        var entity = {
+                            'component': component
+                        };
 
                         startRequests.push(updateResource(d.component.uri, entity).done(function (response) {
-                            if (nf.CanvasUtils.isProcessor(selected)) {
-                                nf.Processor.set(response.processor);
-                            } else if (nf.CanvasUtils.isProcessGroup(selected)) {
-                                nf.ProcessGroup.set(response.processGroup);
+                            if (nf.CanvasUtils.isProcessGroup(selected)) {
+                                nf.ProcessGroup.set(response);
 
                                 // reload the group's connections
-                                var connections = nf.Connection.getComponentConnections(response.processGroup.id);
+                                var connections = nf.Connection.getComponentConnections(response.id);
                                 $.each(connections, function (_, connection) {
                                     nf.Connection.reload(connection);
                                 });
-                            } else if (nf.CanvasUtils.isInputPort(selected)) {
-                                nf.Port.set(response.inputPort);
-                            } else if (nf.CanvasUtils.isOutputPort(selected)) {
-                                nf.Port.set(response.outputPort);
+                            } else {
+                                nf[d.type].set(response);
                             }
                         }));
                     });
@@ -588,7 +568,7 @@ nf.Actions = (function () {
             if (selection.empty()) {
                 // build the entity
                 var entity = {
-                    'processGroup': {
+                    'component': {
                         'id': nf.Canvas.getGroupId(),
                         'running': false
                     }
@@ -615,7 +595,7 @@ nf.Actions = (function () {
 
                         // processor endpoint does not use running flag...
                         var component = {
-                            'id': d.component.id,
+                            'id': d.id,
                         };
                         if (nf.CanvasUtils.isProcessor(selected) || nf.CanvasUtils.isInputPort(selected) || nf.CanvasUtils.isOutputPort(selected)) {
                             component['state'] = 'STOPPED';
@@ -624,24 +604,21 @@ nf.Actions = (function () {
                         }
 
                         // build the entity
-                        var entity = {};
-                        entity[nf[d.type].getEntityKey(d)] = component;
+                        var entity = {
+                            'component': component
+                        };
 
                         stopRequests.push(updateResource(d.component.uri, entity).done(function (response) {
-                            if (nf.CanvasUtils.isProcessor(selected)) {
-                                nf.Processor.set(response.processor);
-                            } else if (nf.CanvasUtils.isProcessGroup(selected)) {
-                                nf.ProcessGroup.set(response.processGroup);
+                            if (nf.CanvasUtils.isProcessGroup(selected)) {
+                                nf.ProcessGroup.set(response);
 
                                 // reload the group's connections
-                                var connections = nf.Connection.getComponentConnections(response.processGroup.id);
+                                var connections = nf.Connection.getComponentConnections(response.id);
                                 $.each(connections, function (_, connection) {
                                     nf.Connection.reload(connection);
                                 });
-                            } else if (nf.CanvasUtils.isInputPort(selected)) {
-                                nf.Port.set(response.inputPort);
-                            } else if (nf.CanvasUtils.isOutputPort(selected)) {
-                                nf.Port.set(response.outputPort);
+                            } else {
+                                nf[d.type].set(response);
                             }
                         }));
                     });
@@ -669,15 +646,16 @@ nf.Actions = (function () {
             // start each selected component
             componentsToEnable.each(function (d) {
                 // build the entity
-                var entity = {};
-                entity[nf[d.type].getEntityKey()] = {
-                    'id': d.component.id,
-                    'transmitting': true
+                var entity = {
+                    'component': {
+                        'id': d.id,
+                        'transmitting': true
+                    }
                 };
 
                 // start transmitting
                 updateResource(d.component.uri, entity).done(function (response) {
-                    nf.RemoteProcessGroup.set(response.remoteProcessGroup);
+                    nf.RemoteProcessGroup.set(response);
                 });
             });
         },
@@ -695,14 +673,15 @@ nf.Actions = (function () {
             // stop each selected component
             componentsToDisable.each(function (d) {
                 // build the entity
-                var entity = {};
-                entity[nf[d.type].getEntityKey()] = {
-                    'id': d.component.id,
-                    'transmitting': false
+                var entity = {
+                    'component': {
+                        'id': d.id,
+                        'transmitting': false
+                    }
                 };
 
                 updateResource(d.component.uri, entity).done(function (response) {
-                    nf.RemoteProcessGroup.set(response.remoteProcessGroup);
+                    nf.RemoteProcessGroup.set(response);
                 });
             });
         },
@@ -735,7 +714,7 @@ nf.Actions = (function () {
             if (selection.size() === 1) {
                 var selectionData = selection.datum();
                 if (nf.CanvasUtils.isProcessor(selection)) {
-                    nf.ProcessorDetails.showDetails(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.ProcessorDetails.showDetails(nf.Canvas.getGroupId(), selectionData.id);
                 } else if (nf.CanvasUtils.isProcessGroup(selection)) {
                     nf.ProcessGroupDetails.showDetails(selection);
                 } else if (nf.CanvasUtils.isRemoteProcessGroup(selection)) {
@@ -743,7 +722,7 @@ nf.Actions = (function () {
                 } else if (nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection)) {
                     nf.PortDetails.showDetails(selection);
                 } else if (nf.CanvasUtils.isConnection(selection)) {
-                    nf.ConnectionDetails.showDetails(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.ConnectionDetails.showDetails(nf.Canvas.getGroupId(), selectionData.id);
                 }
             }
         },
@@ -771,13 +750,13 @@ nf.Actions = (function () {
             if (selection.size() === 1) {
                 var selectionData = selection.datum();
                 if (nf.CanvasUtils.isProcessor(selection)) {
-                    nf.StatusHistory.showProcessorChart(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.StatusHistory.showProcessorChart(nf.Canvas.getGroupId(), selectionData.id);
                 } else if (nf.CanvasUtils.isProcessGroup(selection)) {
-                    nf.StatusHistory.showProcessGroupChart(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.StatusHistory.showProcessGroupChart(nf.Canvas.getGroupId(), selectionData.id);
                 } else if (nf.CanvasUtils.isRemoteProcessGroup(selection)) {
-                    nf.StatusHistory.showRemoteProcessGroupChart(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.StatusHistory.showRemoteProcessGroupChart(nf.Canvas.getGroupId(), selectionData.id);
                 } else if (nf.CanvasUtils.isConnection(selection)) {
-                    nf.StatusHistory.showConnectionChart(nf.Canvas.getGroupId(), selectionData.component.id);
+                    nf.StatusHistory.showConnectionChart(nf.Canvas.getGroupId(), selectionData.id);
                 }
             }
         },
@@ -828,11 +807,11 @@ nf.Actions = (function () {
                         nf.Client.setRevision(response.revision);
 
                         // remove the component/connection in question
-                        nf[selectionData.type].remove(selectionData.component.id);
+                        nf[selectionData.type].remove(selectionData.id);
 
                         // if the selection is a connection, reload the source and destination accordingly
                         if (nf.CanvasUtils.isConnection(selection) === false) {
-                            var connections = nf.Connection.getComponentConnections(selectionData.component.id);
+                            var connections = nf.Connection.getComponentConnections(selectionData.id);
                             if (connections.length > 0) {
                                 var ids = [];
                                 $.each(connections, function (_, connection) {
@@ -869,11 +848,11 @@ nf.Actions = (function () {
                             // go through each component being removed
                             selection.each(function (d) {
                                 // remove the corresponding entry
-                                addComponent(d.type, d.component.id);
+                                addComponent(d.type, d.id);
 
                                 // if this is not a connection, see if it has any connections that need to be removed
                                 if (d.type !== 'Connection') {
-                                    var connections = nf.Connection.getComponentConnections(d.component.id);
+                                    var connections = nf.Connection.getComponentConnections(d.id);
                                     if (connections.length > 0) {
                                         $.each(connections, function (_, connection) {
                                             addComponent('Connection', connection.id);
@@ -1065,7 +1044,7 @@ nf.Actions = (function () {
                     // issue the request to delete the flow files
                     $.ajax({
                         type: 'POST',
-                        url: '../nifi-api/flowfile-queues/' + connection.component.id + '/drop-requests',
+                        url: '../nifi-api/flowfile-queues/' + connection.id + '/drop-requests',
                         dataType: 'json',
                         contentType: 'application/json'
                     }).done(function(response) {
@@ -1365,10 +1344,10 @@ nf.Actions = (function () {
 
                         // copy the snippet to the new location
                         nf.Snippet.copy(snippet.id, origin).done(function (copyResponse) {
-                            var snippetContents = copyResponse.contents;
+                            var snippetFlow = copyResponse.flow;
 
                             // update the graph accordingly
-                            nf.Graph.add(snippetContents, true);
+                            nf.Graph.add(snippetFlow, true);
 
                             // update component visibility
                             nf.Canvas.View.updateVisibility();
@@ -1424,7 +1403,7 @@ nf.Actions = (function () {
             // determine the current max zIndex
             var maxZIndex = -1;
             $.each(nf.Connection.get(), function (_, otherConnection) {
-                if (connection.component.id !== otherConnection.component.id && otherConnection.component.zIndex > maxZIndex) {
+                if (connection.id !== otherConnection.id && otherConnection.component.zIndex > maxZIndex) {
                     maxZIndex = otherConnection.component.zIndex;
                 }
             });
@@ -1437,8 +1416,8 @@ nf.Actions = (function () {
                 // build the connection entity
                 var connectionEntity = {
                     'revision': nf.Client.getRevision(),
-                    'connection': {
-                        'id': connection.component.id,
+                    'component': {
+                        'id': connection.id,
                         'zIndex': zIndex
                     }
                 };
@@ -1452,7 +1431,7 @@ nf.Actions = (function () {
                     contentType: 'application/json'
                 }).done(function (response) {
                     // update the edge's zIndex
-                    nf.Connection.set(response.connection);
+                    nf.Connection.set(response);
                     nf.Connection.reorder();
 
                     // update the revision

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
index 01abd31..1b23262 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
@@ -151,50 +151,54 @@ nf.Birdseye = (function () {
         $.each(components.labels, function (_, d) {
             var color = nf.Label.defaultColor();
 
-            // use the specified color if appropriate
-            if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) {
-                color = d.component.style['background-color'];
+            if (d.accessPolicy.canRead) {
+                // use the specified color if appropriate
+                if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) {
+                    color = d.component.style['background-color'];
+                }
             }
 
             context.fillStyle = color;
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height);
         });
 
         // funnels
         context.fillStyle = '#9f6000';
         $.each(components.funnels, function (_, d) {
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height);
         });
 
         // ports
         context.fillStyle = '#aaa';
         $.each(components.ports, function (_, d) {
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height);
         });
 
         // remote process groups
         context.fillStyle = '#294c58';
         $.each(components.remoteProcessGroups, function (_, d) {
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height);
         });
 
         // process groups
         context.fillStyle = '#294c58';
         $.each(components.processGroups, function (_, d) {
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.x, d.y, d.dimensions.width, d.dimensions.height);
         });
 
         // processors
         $.each(components.processors, function (_, d) {
             var color = nf.Processor.defaultColor();
 
-            // use the specified color if appropriate
-            if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) {
-                color = d.component.style['background-color'];
+            if (d.accessPolicy.canRead) {
+                // use the specified color if appropriate
+                if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) {
+                    color = d.component.style['background-color'];
+                }
             }
 
             context.fillStyle = color;
-            context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height);
+            context.fillRect(d.x, d.y, d.dimensions.width, d.dimensions.height);
         });
 
         context.restore();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
index 6ed6c5d..fbe4b7d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
@@ -166,12 +166,12 @@ nf.CanvasHeader = (function () {
                                     if (color !== selectedData.component.style['background-color']) {
                                         // build the request entity
                                         var entity = {
-                                            'revision': nf.Client.getRevision()
-                                        };
-                                        entity[nf[selectedData.type].getEntityKey()] = {
-                                            'id': selectedData.component.id,
-                                            'style': {
-                                                'background-color': color
+                                            'revision': nf.Client.getRevision(),
+                                            'component': {
+                                                'id': selectedData.id,
+                                                'style': {
+                                                    'background-color': color
+                                                }
                                             }
                                         };
 
@@ -186,12 +186,8 @@ nf.CanvasHeader = (function () {
                                             // update the revision
                                             nf.Client.setRevision(response.revision);
 
-                                            // update the processor
-                                            if (nf.CanvasUtils.isProcessor(selected)) {
-                                                nf.Processor.set(response.processor);
-                                            } else {
-                                                nf.Label.set(response.label);
-                                            }
+                                            // update the component
+                                            nf[selectedData.type].set(response);
                                         }).fail(function (xhr, status, error) {
                                             if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) {
                                                 nf.Dialog.showOkDialog({

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js
index 8aade5c..9cae764 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js
@@ -109,61 +109,62 @@ nf.CanvasToolbar = (function () {
             }
 
             // only refresh the toolbar if DFM
-            if (nf.Common.isDFM()) {
-                var selection = nf.CanvasUtils.getSelection();
+            var selection = nf.CanvasUtils.getSelection();
+            if (nf.CanvasUtils.canModify(selection) === false) {
+                return;
+            }
 
-                // if all selected components are deletable enable the delete button
-                if (!selection.empty()) {
-                    var enableDelete = true;
-                    selection.each(function (d) {
-                        if (!nf.CanvasUtils.isDeletable(d3.select(this))) {
-                            enableDelete = false;
-                            return false;
-                        }
-                    });
-                    if (enableDelete) {
-                        actions['delete'].enable();
-                    } else {
-                        actions['delete'].disable();
+            // if all selected components are deletable enable the delete button
+            if (!selection.empty()) {
+                var enableDelete = true;
+                selection.each(function (d) {
+                    if (!nf.CanvasUtils.isDeletable(d3.select(this))) {
+                        enableDelete = false;
+                        return false;
                     }
+                });
+                if (enableDelete) {
+                    actions['delete'].enable();
                 } else {
                     actions['delete'].disable();
                 }
+            } else {
+                actions['delete'].disable();
+            }
 
-                // if there are any copyable components enable the button
-                if (nf.CanvasUtils.isCopyable(selection)) {
-                    actions['copy'].enable();
-                } else {
-                    actions['copy'].disable();
-                }
+            // if there are any copyable components enable the button
+            if (nf.CanvasUtils.isCopyable(selection)) {
+                actions['copy'].enable();
+            } else {
+                actions['copy'].disable();
+            }
 
-                // determine if the selection is groupable
-                if (!selection.empty() && nf.CanvasUtils.isDisconnected(selection)) {
-                    actions['group'].enable();
-                } else {
-                    actions['group'].disable();
-                }
+            // determine if the selection is groupable
+            if (!selection.empty() && nf.CanvasUtils.isDisconnected(selection)) {
+                actions['group'].enable();
+            } else {
+                actions['group'].disable();
+            }
 
-                // if there are any colorable components enable the fill button
-                if (nf.CanvasUtils.isColorable(selection)) {
-                    actions['fill'].enable();
-                } else {
-                    actions['fill'].disable();
-                }
-                
-                // ensure the selection supports enable
-                if (nf.CanvasUtils.canEnable(selection)) {
-                    actions['enable'].enable();
-                } else {
-                    actions['enable'].disable();
-                }
+            // if there are any colorable components enable the fill button
+            if (nf.CanvasUtils.isColorable(selection)) {
+                actions['fill'].enable();
+            } else {
+                actions['fill'].disable();
+            }
+            
+            // ensure the selection supports enable
+            if (nf.CanvasUtils.canEnable(selection)) {
+                actions['enable'].enable();
+            } else {
+                actions['enable'].disable();
+            }
 
-                // ensure the selection supports disable
-                if (nf.CanvasUtils.canDisable(selection)) {
-                    actions['disable'].enable();
-                } else {
-                    actions['disable'].disable();
-                }
+            // ensure the selection supports disable
+            if (nf.CanvasUtils.canDisable(selection)) {
+                actions['disable'].enable();
+            } else {
+                actions['disable'].disable();
             }
         }
     };

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js
index de40653..aca5a9e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js
@@ -363,7 +363,7 @@ nf.CanvasToolbox = (function () {
     var createProcessor = function (name, processorType, pt) {
         var processorEntity = {
             'revision': nf.Client.getRevision(),
-            'processor': {
+            'component': {
                 'type': processorType,
                 'name': name,
                 'position': {
@@ -381,13 +381,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.processor)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the processor to the graph
                 nf.Graph.add({
-                    'processors': [response.processor]
+                    'processors': [response]
                 }, true);
 
                 // update component visibility
@@ -454,7 +454,7 @@ nf.CanvasToolbox = (function () {
     var createInputPort = function (portName, pt) {
         var inputPortEntity = {
             'revision': nf.Client.getRevision(),
-            'inputPort': {
+            'component': {
                 'name': portName,
                 'position': {
                     'x': pt.x,
@@ -471,13 +471,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.inputPort)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the port to the graph
                 nf.Graph.add({
-                    'inputPorts': [response.inputPort]
+                    'inputPorts': [response]
                 }, true);
 
                 // update component visibility
@@ -544,7 +544,7 @@ nf.CanvasToolbox = (function () {
     var createOutputPort = function (portName, pt) {
         var outputPortEntity = {
             'revision': nf.Client.getRevision(),
-            'outputPort': {
+            'component': {
                 'name': portName,
                 'position': {
                     'x': pt.x,
@@ -561,13 +561,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.outputPort)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the port to the graph
                 nf.Graph.add({
-                    'outputPorts': [response.outputPort]
+                    'outputPorts': [response]
                 }, true);
 
                 // update component visibility
@@ -588,7 +588,7 @@ nf.CanvasToolbox = (function () {
     var createGroup = function (groupName, pt) {
         var processGroupEntity = {
             'revision': nf.Client.getRevision(),
-            'processGroup': {
+            'component': {
                 'name': groupName,
                 'position': {
                     'x': pt.x,
@@ -605,13 +605,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.processGroup)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
-                // add the processor to the graph
+                // add the process group to the graph
                 nf.Graph.add({
-                    'processGroups': [response.processGroup]
+                    'processGroups': [response]
                 }, true);
 
                 // update component visibility
@@ -675,7 +675,7 @@ nf.CanvasToolbox = (function () {
     var createRemoteProcessGroup = function (remoteProcessGroupUri, pt) {
         var remoteProcessGroupEntity = {
             'revision': nf.Client.getRevision(),
-            'remoteProcessGroup': {
+            'component': {
                 'targetUri': remoteProcessGroupUri,
                 'position': {
                     'x': pt.x,
@@ -684,7 +684,7 @@ nf.CanvasToolbox = (function () {
             }
         };
 
-        // create a new processor of the defined type
+        // create a new remote process group of the defined type
         $.ajax({
             type: 'POST',
             url: config.urls.api + '/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/remote-process-groups',
@@ -692,13 +692,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.remoteProcessGroup)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the processor to the graph
                 nf.Graph.add({
-                    'remoteProcessGroups': [response.remoteProcessGroup]
+                    'remoteProcessGroups': [response]
                 }, true);
 
                 // update component visibility
@@ -718,7 +718,7 @@ nf.CanvasToolbox = (function () {
     var createFunnel = function (pt) {
         var outputPortEntity = {
             'revision': nf.Client.getRevision(),
-            'funnel': {
+            'component': {
                 'position': {
                     'x': pt.x,
                     'y': pt.y
@@ -734,13 +734,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.funnel)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the funnel to the graph
                 nf.Graph.add({
-                    'funnels': [response.funnel]
+                    'funnels': [response]
                 }, true);
 
                 // update the birdseye
@@ -841,7 +841,7 @@ nf.CanvasToolbox = (function () {
             nf.Client.setRevision(response.revision);
 
             // populate the graph accordingly
-            nf.Graph.add(response.contents, true);
+            nf.Graph.add(response.flow, true);
 
             // update component visibility
             nf.Canvas.View.updateVisibility();
@@ -859,7 +859,7 @@ nf.CanvasToolbox = (function () {
     var createLabel = function (pt) {
         var labelEntity = {
             'revision': nf.Client.getRevision(),
-            'label': {
+            'component': {
                 'width': nf.Label.config.width,
                 'height': nf.Label.config.height,
                 'position': {
@@ -877,13 +877,13 @@ nf.CanvasToolbox = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (response) {
-            if (nf.Common.isDefinedAndNotNull(response.label)) {
+            if (nf.Common.isDefinedAndNotNull(response.component)) {
                 // update the revision
                 nf.Client.setRevision(response.revision);
 
                 // add the label to the graph
                 nf.Graph.add({
-                    'labels': [response.label]
+                    'labels': [response]
                 }, true);
 
                 // update the birdseye
@@ -1135,7 +1135,7 @@ nf.CanvasToolbox = (function () {
 
                     // create the group and resolve the deferred accordingly
                     createGroup(groupName, pt).done(function (response) {
-                        deferred.resolve(response.processGroup);
+                        deferred.resolve(response.component);
                     }).fail(function () {
                         deferred.reject();
                     });

http://git-wip-us.apache.org/repos/asf/nifi/blob/ff98d823/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
index 0a9cf28..55c4b49 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
@@ -74,7 +74,7 @@ nf.CanvasUtils = (function () {
 
                         // go through each component being removed
                         components.each(function (d) {
-                            addComponent(d.type, d.component.id);
+                            addComponent(d.type, d.id);
                         });
 
                         // refresh all component types as necessary (handle components that have been removed)
@@ -271,7 +271,7 @@ nf.CanvasUtils = (function () {
 
             // update the processors positioning
             updated.attr('transform', function (d) {
-                return 'translate(' + d.component.position.x + ', ' + d.component.position.y + ')';
+                return 'translate(' + d.position.x + ', ' + d.position.y + ')';
             });
         },
         
@@ -467,7 +467,7 @@ nf.CanvasUtils = (function () {
             offset = nf.Common.isDefinedAndNotNull(offset) ? offset : 0;
 
             // remove any existing tip if necessary
-            var tip = d3.select('#bulletin-tip-' + d.component.id);
+            var tip = d3.select('#bulletin-tip-' + d.id);
             if (!tip.empty()) {
                 tip.remove();
             }
@@ -488,7 +488,7 @@ nf.CanvasUtils = (function () {
                             // if there are bulletins generate a tooltip
                             tip = getTooltipContainer().append('div')
                                     .attr('id', function () {
-                                        return 'bulletin-tip-' + d.component.id;
+                                        return 'bulletin-tip-' + d.id;
                                     })
                                     .attr('class', 'tooltip nifi-tooltip')
                                     .html(function () {
@@ -843,6 +843,36 @@ nf.CanvasUtils = (function () {
 
             return nf.CanvasUtils.supportsModification(selection);
         },
+
+        /**
+         * Determines whether the components in the specified selection are writable.
+         *
+         * @argument {selection} selection      The selection
+         * @return {boolean}            Whether the selection is writable
+         */
+        canModify: function (selection) {
+            var selectionSize = selection.size();
+            var writableSize = selection.filter(function (d) {
+                return d.accessPolicy.canWrite && d.accessPolicy.canRead;
+            }).size();
+            
+            return selectionSize === writableSize;
+        },
+
+        /**
+         * Determines whether the components in the specified selection are readable.
+         *
+         * @argument {selection} selection      The selection
+         * @return {boolean}            Whether the selection is readable
+         */
+        canRead: function (selection) {
+            var selectionSize = selection.size();
+            var readableSize = selection.filter(function (d) {
+                return d.accessPolicy.canRead;
+            }).size();
+
+            return selectionSize === readableSize;
+        },
         
         /**
          * Determines whether the specified selection is in a state to support modification.
@@ -875,7 +905,7 @@ nf.CanvasUtils = (function () {
                 var isSourceConfigurable = false;
                 var isDestinationConfigurable = false;
 
-                var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(selectionData.component);
+                var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(selectionData);
                 var source = d3.select('#id-' + sourceComponentId);
                 if (!source.empty()) {
                     if (nf.CanvasUtils.isRemoteProcessGroup(source) || nf.CanvasUtils.isProcessGroup(source)) {
@@ -885,7 +915,7 @@ nf.CanvasUtils = (function () {
                     }
                 }
 
-                var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(selectionData.component);
+                var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(selectionData);
                 var destination = d3.select('#id-' + destinationComponentId);
                 if (!destination.empty()) {
                     if (nf.CanvasUtils.isRemoteProcessGroup(destination) || nf.CanvasUtils.isProcessGroup(destination)) {
@@ -958,12 +988,12 @@ nf.CanvasUtils = (function () {
                 var selected = d3.select(this);
                 if (nf.CanvasUtils.isConnection(selected)) {
                     var sourceIncluded = !selection.filter(function (source) {
-                        var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d.component);
-                        return sourceComponentId === source.component.id;
+                        var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d);
+                        return sourceComponentId === source.id;
                     }).empty();
                     var destinationIncluded = !selection.filter(function (destination) {
-                        var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d.component);
-                        return destinationComponentId === destination.component.id;
+                        var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d);
+                        return destinationComponentId === destination.id;
                     }).empty();
                     return sourceIncluded && destinationIncluded;
                 } else {
@@ -1026,13 +1056,15 @@ nf.CanvasUtils = (function () {
                 if (source.empty() === false) {
                     var sourceData = source.datum();
 
-                    // update the source status if necessary
-                    if (nf.CanvasUtils.isProcessor(source)) {
-                        nf.Processor.reload(sourceData.component);
-                    } else if (nf.CanvasUtils.isInputPort(source)) {
-                        nf.Port.reload(sourceData.component);
-                    } else if (nf.CanvasUtils.isRemoteProcessGroup(source)) {
-                        nf.RemoteProcessGroup.reload(sourceData.component);
+                    if (sourceData.accessPolicy.canRead) {
+                        // update the source status if necessary
+                        if (nf.CanvasUtils.isProcessor(source)) {
+                            nf.Processor.reload(sourceData.component);
+                        } else if (nf.CanvasUtils.isInputPort(source)) {
+                            nf.Port.reload(sourceData.component);
+                        } else if (nf.CanvasUtils.isRemoteProcessGroup(source)) {
+                            nf.RemoteProcessGroup.reload(sourceData.component);
+                        }
                     }
                 }
             }
@@ -1042,11 +1074,13 @@ nf.CanvasUtils = (function () {
                 if (destination.empty() === false) {
                     var destinationData = destination.datum();
 
-                    // update the destination component accordingly
-                    if (nf.CanvasUtils.isProcessor(destination)) {
-                        nf.Processor.reload(destinationData.component);
-                    } else if (nf.CanvasUtils.isRemoteProcessGroup(destination)) {
-                        nf.RemoteProcessGroup.reload(destinationData.component);
+                    if (destinationData.accessPolicy.canRead) {
+                        // update the destination component accordingly
+                        if (nf.CanvasUtils.isProcessor(destination)) {
+                            nf.Processor.reload(destinationData.component);
+                        } else if (nf.CanvasUtils.isRemoteProcessGroup(destination)) {
+                            nf.RemoteProcessGroup.reload(destinationData.component);
+                        }
                     }
                 }
             }
@@ -1060,9 +1094,9 @@ nf.CanvasUtils = (function () {
          * @param {object} connection   The connection in question
          */
         getConnectionSourceComponentId: function (connection) {
-            var sourceId = connection.source.id;
-            if (connection.source.groupId !== nf.Canvas.getGroupId()) {
-                sourceId = connection.source.groupId;
+            var sourceId = connection.sourceId;
+            if (connection.sourceGroupId !== nf.Canvas.getGroupId()) {
+                sourceId = connection.sourceGroupId;
             }
             return sourceId;
         },
@@ -1075,9 +1109,9 @@ nf.CanvasUtils = (function () {
          * @param {object} connection   The connection in question
          */
         getConnectionDestinationComponentId: function (connection) {
-            var destinationId = connection.destination.id;
-            if (connection.destination.groupId !== nf.Canvas.getGroupId()) {
-                destinationId = connection.destination.groupId;
+            var destinationId = connection.destinationId;
+            if (connection.destinationGroupId !== nf.Canvas.getGroupId()) {
+                destinationId = connection.destinationGroupId;
             }
             return destinationId;
         },
@@ -1162,11 +1196,11 @@ nf.CanvasUtils = (function () {
             selection.each(function (d) {
                 var selected = d3.select(this);
                 if (!nf.CanvasUtils.isConnection(selected)) {
-                    if (nf.Common.isUndefined(origin.x) || d.component.position.x < origin.x) {
-                        origin.x = d.component.position.x;
+                    if (nf.Common.isUndefined(origin.x) || d.position.x < origin.x) {
+                        origin.x = d.position.x;
                     }
-                    if (nf.Common.isUndefined(origin.y) || d.component.position.y < origin.y) {
-                        origin.y = d.component.position.y;
+                    if (nf.Common.isUndefined(origin.y) || d.position.y < origin.y) {
+                        origin.y = d.position.y;
                     }
                 }
             });
@@ -1200,7 +1234,7 @@ nf.CanvasUtils = (function () {
             var groupData = group.datum();
             
             // move the components into the destination and...
-            moveComponents(components, groupData.component.id).done(function () {
+            moveComponents(components, groupData.id).done(function () {
                 // reload the target group
                 nf.ProcessGroup.reload(groupData.component);
             });
@@ -1223,10 +1257,10 @@ nf.CanvasUtils = (function () {
                 var includesSource = false;
                 var includesDestination = false;
                 selection.each(function (d) {
-                    if (d.component.id === sourceComponentId) {
+                    if (d.id === sourceComponentId) {
                         includesSource = true;
                     }
-                    if (d.component.id === destinationComponentId) {
+                    if (d.id === destinationComponentId) {
                         includesDestination = true;
                     }
                 });
@@ -1237,7 +1271,7 @@ nf.CanvasUtils = (function () {
             // include all components and connections whose source/destination are also selected
             return selection.filter(function (d) {
                 if (d.type === 'Connection') {
-                    return keepConnection(d.component);
+                    return keepConnection(d);
                 } else {
                     return true;
                 }
@@ -1258,17 +1292,17 @@ nf.CanvasUtils = (function () {
             selection.filter(function (d) {
                 return d.type === 'Connection';
             }).each(function (d) {
-                connections.set(d.component.id, d.component);
+                connections.set(d.id, d);
             });
 
             // include components and ensure their connections are included
             selection.filter(function (d) {
                 return d.type !== 'Connection';
             }).each(function (d) {
-                components.set(d.component.id, d.component);
+                components.set(d.id, d.component);
 
                 // check all connections of this component
-                $.each(nf.Connection.getComponentConnections(d.component.id), function (_, connection) {
+                $.each(nf.Connection.getComponentConnections(d.id), function (_, connection) {
                     if (!connections.has(connection.id)) {
                         isDisconnected = false;
                         return false;
@@ -1338,7 +1372,7 @@ nf.CanvasUtils = (function () {
                                         // check the input ports
                                         $.each(inputPorts, function (i, inputPort) {
                                             $.each(connections, function (j, connection) {
-                                                if (inputPort.component.id === connection.destination.id) {
+                                                if (inputPort.id === connection.destination.id) {
                                                     conflictingPorts.push(nf.Common.escapeHtml(inputPort.component.name));
                                                 }
                                             });
@@ -1347,7 +1381,7 @@ nf.CanvasUtils = (function () {
                                         // check the output ports
                                         $.each(outputPorts, function (i, outputPort) {
                                             $.each(connections, function (j, connection) {
-                                                if (outputPort.component.id === connection.source.id) {
+                                                if (outputPort.id === connection.source.id) {
                                                     conflictingPorts.push(nf.Common.escapeHtml(outputPort.component.name));
                                                 }
                                             });
@@ -1385,7 +1419,7 @@ nf.CanvasUtils = (function () {
                                 },
                                 dataType: 'json'
                             }).done(function (response) {
-                                var processGroup = response.processGroup;
+                                var processGroup = response.component;
                                 var processGroupContents = processGroup.contents;
 
                                 var conflictingPorts = [];