com.amazonaws.eclipse.ec2.ui.securitygroups.PermissionsComposite.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.eclipse.ec2.ui.securitygroups.PermissionsComposite.java

Source

/*
 * Copyright 2008-2011 Amazon Technologies, Inc.
 *
 * Licensed 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://aws.amazon.com/apache2.0
 *
 * This file 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 com.amazonaws.eclipse.ec2.ui.securitygroups;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.statushandlers.StatusManager;

import com.amazonaws.eclipse.core.AwsToolkitCore;
import com.amazonaws.eclipse.ec2.Ec2Plugin;
import com.amazonaws.eclipse.ec2.ui.SelectionTable;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
import com.amazonaws.services.ec2.model.DescribeSecurityGroupsRequest;
import com.amazonaws.services.ec2.model.DescribeSecurityGroupsResult;
import com.amazonaws.services.ec2.model.IpPermission;
import com.amazonaws.services.ec2.model.RevokeSecurityGroupIngressRequest;
import com.amazonaws.services.ec2.model.SecurityGroup;
import com.amazonaws.services.ec2.model.UserIdGroupPair;

/**
 * Selection table for users to select individual permissions in a security
 * group.
 */
public class PermissionsComposite extends SelectionTable {

    private PermissionsTableProvider permissionsTableProvider = new PermissionsTableProvider();
    private Action addPermissionAction;
    private Action removePermissionAction;
    private SecurityGroupSelectionComposite securityGroupSelectionComposite;

    /**
     * Comparator to sort permissions.
     *
     * @author Jason Fulghum <fulghum@amazon.com>
     */
    class IpPermissionComparator extends ViewerComparator {
        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
            if (!(e1 instanceof IpPermission && e2 instanceof IpPermission)) {
                return 0;
            }

            IpPermission ipPermission1 = (IpPermission) e1;
            IpPermission ipPermission2 = (IpPermission) e2;

            int comparision = ipPermission1.getIpProtocol().compareTo(ipPermission2.getIpProtocol());

            if (comparision == 0) {
                comparision = ipPermission1.getFromPort() - ipPermission2.getFromPort();
            }

            return comparision;
        }
    }

    /**
     * Content and label provider for security group permission details.
     *
     * @author Jason Fulghum <fulghum@amazon.com>
     */
    private class PermissionsTableProvider extends LabelProvider
            implements ITreeContentProvider, ITableLabelProvider {

        private List<IpPermission> ipPermissions;

        /*
         * IStructuredContentProvider Interface
         */

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
         */
        public Object[] getElements(Object inputElement) {
            if (ipPermissions == null) {
                return null;
            }

            return ipPermissions.toArray();
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
         */
        @SuppressWarnings("unchecked")
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            if (newInput instanceof List) {
                ipPermissions = (List<IpPermission>) newInput;
            }
        }

        /*
         * ITableLableProvider Interface
         */

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
         */
        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
         */
        public String getColumnText(Object element, int columnIndex) {
            if (!(element instanceof IpPermission)) {
                return "???";
            }

            IpPermission ipPermission = (IpPermission) element;

            switch (columnIndex) {
            case 0:
                return ipPermission.getIpProtocol();
            case 1:
                return formatPortRange(ipPermission);
            case 2:
                return formatUidGroupPairs(ipPermission);
            case 3:
                return formatIpRanges(ipPermission);
            }

            return "?";
        }

        private String formatIpRanges(IpPermission ipPermission) {
            StringBuilder builder = new StringBuilder();
            for (String s : ipPermission.getIpRanges()) {
                if (builder.length() > 0) {
                    builder.append(", ");
                }

                builder.append(s);
            }
            return builder.toString();
        }

        private String formatUidGroupPairs(IpPermission ipPermission) {
            StringBuilder builder = new StringBuilder();
            for (UserIdGroupPair s : ipPermission.getUserIdGroupPairs()) {
                if (builder.length() > 0) {
                    builder.append(", ");
                }

                builder.append(s.getUserId() + ":" + s.getGroupName());
            }
            return builder.toString();
        }

        private String formatPortRange(IpPermission ipPermission) {
            int fromPort = ipPermission.getFromPort();
            int toPort = ipPermission.getToPort();

            if (fromPort == toPort) {
                return Integer.toString(fromPort);
            } else {
                return fromPort + " - " + toPort;
            }
        }

        public Object[] getChildren(Object parentElement) {
            return new Object[0];
        }

        public Object getParent(Object element) {
            return null;
        }

        public boolean hasChildren(Object element) {
            return false;
        }
    }

    /**
     * Creates a new PermissionsComposite with the specified parent.
     *
     * @param parent the parent of this new Composite.
     */
    public PermissionsComposite(Composite parent) {
        super(parent);

        viewer.setContentProvider(permissionsTableProvider);
        viewer.setLabelProvider(permissionsTableProvider);
        viewer.setComparator(new IpPermissionComparator());
    }

    /**
     * Refreshes the data in the permissions table
     */
    public void refreshPermissions() {
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                SecurityGroup selectedSecurityGroup = securityGroupSelectionComposite.getSelectedSecurityGroup();

                if (selectedSecurityGroup == null) {
                    setInput(new ArrayList<IpPermission>());
                    return;
                }

                String groupName = selectedSecurityGroup.getGroupName();

                new RefreshPermissionsThread(groupName).start();
            }
        });
    }

    /**
     * Sets the security group selection table that controls which security
     * group's permissions are shown in this selection table.
     *
     * @param securityGroupSelectionComposite
     *            The security group selection table that controls which
     *            security group's permissions are shown in this selection
     *            table.
     */
    public void setSecurityGroupComposite(SecurityGroupSelectionComposite securityGroupSelectionComposite) {

        this.securityGroupSelectionComposite = securityGroupSelectionComposite;
    }

    /**
     * Returns the currently selected permission.
     *
     * @return The currently selected permission.
     */
    public IpPermission getSelectedIpPermission() {
        Object obj = this.getSelection();

        return (IpPermission) obj;
    }

    /*
     * SelectionTable Interface
     */

    /* (non-Javadoc)
     * @see com.amazonaws.eclipse.ec2.ui.SelectionTable#fillContextMenu(org.eclipse.jface.action.IMenuManager)
     */
    @Override
    protected void fillContextMenu(IMenuManager manager) {
        if (securityGroupSelectionComposite.getSelectedSecurityGroup() == null) {
            addPermissionAction.setEnabled(false);
        } else {
            addPermissionAction.setEnabled(true);
        }

        if (this.getSelection() == null) {
            removePermissionAction.setEnabled(false);
        } else {
            removePermissionAction.setEnabled(true);
        }

        manager.add(addPermissionAction);
        manager.add(removePermissionAction);
    }

    /* (non-Javadoc)
     * @see com.amazonaws.eclipse.ec2.ui.SelectionTable#makeActions()
     */
    @Override
    protected void makeActions() {
        addPermissionAction = new Action() {
            public void run() {
                String securityGroup = securityGroupSelectionComposite.getSelectedSecurityGroup().getGroupName();

                EditSecurityGroupPermissionEntryDialog dialog = new EditSecurityGroupPermissionEntryDialog(
                        Display.getCurrent().getActiveShell(), securityGroup);
                if (dialog.open() != IDialogConstants.OK_ID)
                    return;

                new AuthorizePermissionsThread(securityGroup, dialog).start();
            }
        };
        addPermissionAction.setText("Add Permissions...");
        addPermissionAction.setToolTipText("Add new permissions to the selected security group");
        addPermissionAction.setImageDescriptor(Ec2Plugin.getDefault().getImageRegistry().getDescriptor("add"));

        removePermissionAction = new Action() {
            public void run() {
                String securityGroup = securityGroupSelectionComposite.getSelectedSecurityGroup().getGroupName();
                new RevokePermissionsThread(securityGroup, getSelectedIpPermission()).start();
            }
        };
        removePermissionAction.setText("Remove Permissions");
        removePermissionAction.setToolTipText("Remove the selected permission from the selected security group");
        removePermissionAction
                .setImageDescriptor(Ec2Plugin.getDefault().getImageRegistry().getDescriptor("remove"));
    }

    /* (non-Javadoc)
     * @see com.amazonaws.eclipse.ec2.ui.SelectionTable#createColumns()
     */
    @Override
    protected void createColumns() {
        newColumn("Protocol", 10);
        newColumn("Port", 10);
        newColumn("User:Group", 10);
        newColumn("Source CIDR", 70);
    }

    /**
     * Sets the input for this permissions composite, ensuring that the widgets
     * are updated in the UI thread.
     *
     * @param ipPermissions
     *            The list of permissions to display in this permissions
     *            composite.
     */
    private void setInput(final List<IpPermission> ipPermissions) {
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                viewer.setInput(ipPermissions);
                packColumns();
            }
        });
    }

    /*
     * Private Threads for making EC2 service calls
     */

    /**
     * Thread for making an EC2 service call to list all permissions in an
     * EC2 security group.
     */
    private class RefreshPermissionsThread extends Thread {
        private final String groupName;

        /**
         * Creates a new RefreshPermissionsThread ready to be started to query
         * the permissions in the specified EC2 security group and update the
         * permissions list widget.
         *
         * @param groupName
         *            The EC2 security group whose permissions are to be
         *            refreshed.
         */
        public RefreshPermissionsThread(String groupName) {
            this.groupName = groupName;
        }

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            try {

                DescribeSecurityGroupsRequest request = new DescribeSecurityGroupsRequest();
                request.withGroupNames(groupName);
                DescribeSecurityGroupsResult response = getAwsEc2Client().describeSecurityGroups(request);

                List<SecurityGroup> securityGroups = response.getSecurityGroups();

                if (securityGroups.isEmpty())
                    return;

                setInput(securityGroups.get(0).getIpPermissions());
            } catch (Exception e) {
                // Only log an error if the account info is valid and we
                // actually expected this call to work
                if (AwsToolkitCore.getDefault().getAccountInfo().isValid()) {
                    Status status = new Status(Status.ERROR, Ec2Plugin.PLUGIN_ID,
                            "Unable to refresh security group permissions: " + e.getMessage(), e);
                    StatusManager.getManager().handle(status, StatusManager.LOG);
                }
            }
        }
    }

    /**
     * Thread for making an EC2 service call to authorize new permissions in an
     * EC2 security group.
     */
    private class AuthorizePermissionsThread extends Thread {

        private final EditSecurityGroupPermissionEntryDialog dialog;
        private final String securityGroup;

        /**
         * Creates a new AuthorizePermissionsThread ready to be run to add the
         * permissions detailed in the specified permission entry dialog to the
         * specified security group.
         *
         * @param securityGroup
         *            The security group in which to authorize the new
         *            permissions.
         * @param dialog
         *            The permission entry dialog containing the user input on
         *            what permissions to authorize.
         */
        public AuthorizePermissionsThread(String securityGroup, EditSecurityGroupPermissionEntryDialog dialog) {
            this.securityGroup = securityGroup;
            this.dialog = dialog;
        }

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            try {
                if (dialog.isUserGroupPermission()) {
                    String groupName = dialog.getUserGroupPermissionComposite().getSecurityGroup();
                    String userId = dialog.getUserGroupPermissionComposite().getUserId();

                    AuthorizeSecurityGroupIngressRequest request = new AuthorizeSecurityGroupIngressRequest();
                    request.setGroupName(securityGroup);
                    request.setSourceSecurityGroupName(groupName);
                    request.setSourceSecurityGroupOwnerId(userId);

                    getAwsEc2Client().authorizeSecurityGroupIngress(request);
                } else {
                    String protocol = dialog.getPortRangePermissionComposite().getProtocol();
                    int fromPort = dialog.getPortRangePermissionComposite().getFromPort();
                    int toPort = dialog.getPortRangePermissionComposite().getToPort();
                    String networkMask = dialog.getPortRangePermissionComposite().getNetwork();

                    AuthorizeSecurityGroupIngressRequest request = new AuthorizeSecurityGroupIngressRequest();
                    request.setGroupName(securityGroup);
                    request.setIpProtocol(protocol);
                    request.setFromPort(fromPort);
                    request.setToPort(toPort);
                    request.setCidrIp(networkMask);

                    getAwsEc2Client().authorizeSecurityGroupIngress(request);
                }
            } catch (Exception e) {
                Status status = new Status(Status.ERROR, Ec2Plugin.PLUGIN_ID,
                        "Unable to add permission to group: " + e.getMessage(), e);
                StatusManager.getManager().handle(status, StatusManager.BLOCK | StatusManager.LOG);
            }

            refreshPermissions();
        }

    }

    /**
     * Thread for making an EC2 service call to revoke specified permissions in
     * an EC2 security group.
     */
    private class RevokePermissionsThread extends Thread {

        private final IpPermission ipPermission;
        private final String securityGroup;

        /**
         * Creates a new RevokePermissionsThread ready to be run to remove the
         * specified permissions from the specified EC2 security group.
         *
         * @param securityGroup
         *            The group from which to revoke permissions.
         * @param permission
         *            The permissions to revoke.
         */
        public RevokePermissionsThread(String securityGroup, IpPermission permission) {
            this.securityGroup = securityGroup;
            this.ipPermission = permission;
        }

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            try {
                AmazonEC2 client = getAwsEc2Client();

                if (ipPermission.getUserIdGroupPairs().isEmpty()) {
                    for (String ipRange : ipPermission.getIpRanges()) {
                        RevokeSecurityGroupIngressRequest request = new RevokeSecurityGroupIngressRequest();
                        request.setGroupName(securityGroup);
                        request.setIpProtocol(ipPermission.getIpProtocol());
                        request.setFromPort(ipPermission.getFromPort());
                        request.setToPort(ipPermission.getToPort());
                        request.setCidrIp(ipRange);

                        client.revokeSecurityGroupIngress(request);
                    }
                } else {
                    for (UserIdGroupPair pair : ipPermission.getUserIdGroupPairs()) {
                        RevokeSecurityGroupIngressRequest request = new RevokeSecurityGroupIngressRequest();
                        request.setGroupName(securityGroup);
                        request.setSourceSecurityGroupName(pair.getGroupName());
                        request.setSourceSecurityGroupOwnerId(pair.getUserId());
                        getAwsEc2Client().revokeSecurityGroupIngress(request);
                    }
                }
            } catch (Exception e) {
                Status status = new Status(Status.ERROR, Ec2Plugin.PLUGIN_ID,
                        "Unable to remove security group permissions: " + e.getMessage(), e);
                StatusManager.getManager().handle(status, StatusManager.BLOCK | StatusManager.LOG);
            }

            refreshPermissions();
        }
    }

}