org.zalando.stups.fullstop.plugin.SubnetPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.zalando.stups.fullstop.plugin.SubnetPlugin.java

Source

/**
 * Copyright 2015 Zalando SE
 *
 * 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://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.zalando.stups.fullstop.plugin;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEvent;
import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEventData;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.DescribeRouteTablesRequest;
import com.amazonaws.services.ec2.model.DescribeRouteTablesResult;
import com.amazonaws.services.ec2.model.Filter;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Route;
import com.amazonaws.services.ec2.model.RouteTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zalando.stups.fullstop.aws.ClientProvider;
import org.zalando.stups.fullstop.violation.entity.Violation;
import org.zalando.stups.fullstop.violation.ViolationStore;
import org.zalando.stups.fullstop.violation.entity.ViolationBuilder;

import java.util.List;
import java.util.stream.Collectors;

import static com.google.common.collect.Lists.newArrayList;
import static java.lang.String.format;
import static org.zalando.stups.fullstop.events.CloudtrailEventSupport.getAccountId;
import static org.zalando.stups.fullstop.events.CloudtrailEventSupport.getInstanceIds;
import static org.zalando.stups.fullstop.events.CloudtrailEventSupport.getRegionAsString;

/**
 * @author mrandi
 */
@Component
public class SubnetPlugin extends AbstractFullstopPlugin {

    private static final Logger LOG = LoggerFactory.getLogger(SubnetPlugin.class);

    private static final String EC2_SOURCE_EVENTS = "ec2.amazonaws.com";
    private static final String EVENT_NAME = "RunInstances";

    private final ClientProvider cachingClientProvider;
    private final ViolationStore violationStore;

    @Autowired
    public SubnetPlugin(final ClientProvider cachingClientProvider, final ViolationStore violationStore) {
        this.cachingClientProvider = cachingClientProvider;
        this.violationStore = violationStore;
    }

    @Override
    public boolean supports(final CloudTrailEvent event) {
        CloudTrailEventData cloudTrailEventData = event.getEventData();
        String eventSource = cloudTrailEventData.getEventSource();
        String eventName = cloudTrailEventData.getEventName();

        return eventSource.equals(EC2_SOURCE_EVENTS) && eventName.equals(EVENT_NAME);
    }

    @Override
    public void processEvent(final CloudTrailEvent event) {
        List<String> subnetIds = newArrayList();
        List<Filter> SubnetIdFilters = newArrayList();
        DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest();
        List<String> instanceIds = getInstanceIds(event);
        AmazonEC2Client amazonEC2Client = cachingClientProvider.getClient(AmazonEC2Client.class,
                event.getEventData().getAccountId(),
                Region.getRegion(Regions.fromName(event.getEventData().getAwsRegion())));

        DescribeInstancesResult describeInstancesResult = null;
        try {
            describeInstancesResult = amazonEC2Client
                    .describeInstances(describeInstancesRequest.withInstanceIds(instanceIds));
        } catch (AmazonServiceException e) {
            violationStore.save(new ViolationBuilder(e.getMessage()).withEvent(event).build());
            return;
        }

        List<Reservation> reservations = describeInstancesResult.getReservations();
        for (Reservation reservation : reservations) {
            List<Instance> instances = reservation.getInstances();
            subnetIds.addAll(instances.stream().map(Instance::getSubnetId).collect(Collectors.toList()));

        }

        SubnetIdFilters.add(new Filter().withName("association.subnet-id").withValues(subnetIds)); // filter by subnetId
        DescribeRouteTablesRequest describeRouteTablesRequest = new DescribeRouteTablesRequest()
                .withFilters(SubnetIdFilters);
        DescribeRouteTablesResult describeRouteTablesResult = amazonEC2Client
                .describeRouteTables(describeRouteTablesRequest);
        List<RouteTable> routeTables = describeRouteTablesResult.getRouteTables();
        if (routeTables == null || routeTables.size() == 0) {
            violationStore.save(new ViolationBuilder(
                    format("Instances %s have no routing information associated", instanceIds.toString()))
                            .withEvent(event).build());
            return;
        }
        for (RouteTable routeTable : routeTables) {
            List<Route> routes = routeTable.getRoutes();
            routes.stream()
                    .filter(route -> route.getState().equals("active") && route.getNetworkInterfaceId() != null
                            && !route.getNetworkInterfaceId().startsWith("eni"))
                    .forEach(route -> violationStore.save(

                            new ViolationBuilder(format("ROUTES: instance %s is running in a public subnet %s",
                                    route.getInstanceId(), route.getNetworkInterfaceId())).withEvent(event)
                                            .build()));
        }

    }

}