keywhiz.KeywhizService.java Source code

Java tutorial

Introduction

Here is the source code for keywhiz.KeywhizService.java

Source

/*
 * Copyright (C) 2015 Square, 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://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 keywhiz;

import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import io.dropwizard.Application;
import io.dropwizard.java8.Java8Bundle;
import io.dropwizard.jersey.setup.JerseyEnvironment;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import javax.sql.DataSource;
import keywhiz.auth.mutualssl.ClientCertificateFilter;
import keywhiz.auth.xsrf.XsrfServletFilter;
import keywhiz.commands.AddUserCommand;
import keywhiz.commands.DbSeedCommand;
import keywhiz.commands.GenerateAesKeyCommand;
import keywhiz.commands.MigrateCommand;
import keywhiz.commands.PreviewMigrateCommand;
import keywhiz.service.filters.CookieRenewingFilter;
import keywhiz.service.filters.SecurityHeadersFilter;
import keywhiz.service.providers.AuthResolver;
import keywhiz.service.providers.AutomationClientAuthFactory;
import keywhiz.service.providers.ClientAuthFactory;
import keywhiz.service.providers.UserAuthFactory;
import keywhiz.service.resources.SecretDeliveryResource;
import keywhiz.service.resources.SecretsDeliveryResource;
import keywhiz.service.resources.StatusResource;
import keywhiz.service.resources.admin.*;
import keywhiz.service.resources.automation.AutomationClientResource;
import keywhiz.service.resources.automation.AutomationEnrollClientGroupResource;
import keywhiz.service.resources.automation.AutomationGroupResource;
import keywhiz.service.resources.automation.AutomationSecretAccessResource;
import keywhiz.service.resources.automation.AutomationSecretResource;
import keywhiz.service.resources.automation.v2.ClientResource;
import keywhiz.service.resources.automation.v2.GroupResource;
import keywhiz.service.resources.automation.v2.SecretResource;
import org.flywaydb.core.Flyway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Starting point for Keywhiz, an implementation of the Dropwizard Service.
 */
public class KeywhizService extends Application<KeywhizConfig> {
    /**
     * Entry point into application.
     * @param args passed onto {@link #run(String[])}
     * @throws Exception for any uncaught application exception
     */
    public static void main(String[] args) throws Exception {
        new KeywhizService().run(args);
    }

    private static final Logger logger = LoggerFactory.getLogger(KeywhizService.class);

    private Injector injector;

    @SuppressWarnings("unused")
    public Injector getInjector() {
        return injector;
    }

    public void setInjector(Injector injector) {
        this.injector = injector;
    }

    @Override
    public String getName() {
        return "keywhiz";
    }

    @Override
    public void initialize(Bootstrap<KeywhizConfig> bootstrap) {
        customizeObjectMapper(bootstrap.getObjectMapper());

        logger.debug("Registering commands");
        bootstrap.addCommand(new PreviewMigrateCommand());
        bootstrap.addCommand(new MigrateCommand());
        bootstrap.addCommand(new DbSeedCommand());
        bootstrap.addCommand(new GenerateAesKeyCommand());
        bootstrap.addCommand(new AddUserCommand());

        logger.debug("Registering bundles");
        bootstrap.addBundle(new Java8Bundle());
        bootstrap.addBundle(new NamedAssetsBundle());
        bootstrap.addBundle(new UiAssetsBundle());
    }

    @SuppressWarnings("unchecked")
    @Override
    public void run(KeywhizConfig config, Environment environment) throws Exception {
        if (injector == null) {
            logger.debug("No existing guice injector; creating new one");
            injector = Guice.createInjector(new ServiceModule(config, environment));
        }

        JerseyEnvironment jersey = environment.jersey();

        logger.debug("Registering resource filters");
        jersey.register(injector.getInstance(ClientCertificateFilter.class));

        logger.debug("Registering servlet filters");
        environment.servlets()
                .addFilter("security-headers-filter", injector.getInstance(SecurityHeadersFilter.class))
                .addMappingForUrlPatterns(null, /* Default is for requests */
                        false /* Can be after other filters */, "/*" /* Every request */);
        jersey.register(injector.getInstance(CookieRenewingFilter.class));

        environment.servlets().addFilter("xsrf-filter", injector.getInstance(XsrfServletFilter.class))
                .addMappingForUrlPatterns(null /* Default is for requests */,
                        false /* Can be after other filters */, "/admin/*" /* Path to filter on */);

        logger.debug("Registering providers");
        jersey.register(new AuthResolver.Binder(injector.getInstance(ClientAuthFactory.class),
                injector.getInstance(AutomationClientAuthFactory.class),
                injector.getInstance(UserAuthFactory.class)));

        logger.debug("Registering resources");
        jersey.register(injector.getInstance(ClientResource.class));
        jersey.register(injector.getInstance(ClientsResource.class));
        jersey.register(injector.getInstance(GroupResource.class));
        jersey.register(injector.getInstance(GroupsResource.class));
        jersey.register(injector.getInstance(MembershipResource.class));
        jersey.register(injector.getInstance(SecretsDeliveryResource.class));
        jersey.register(injector.getInstance(SecretResource.class));
        jersey.register(injector.getInstance(SecretsResource.class));
        jersey.register(injector.getInstance(SecretDeliveryResource.class));
        jersey.register(injector.getInstance(SessionLoginResource.class));
        jersey.register(injector.getInstance(SessionLogoutResource.class));
        jersey.register(injector.getInstance(SessionMeResource.class));
        jersey.register(injector.getInstance(AutomationClientResource.class));
        jersey.register(injector.getInstance(AutomationGroupResource.class));
        jersey.register(injector.getInstance(AutomationSecretResource.class));
        jersey.register(injector.getInstance(AutomationEnrollClientGroupResource.class));
        jersey.register(injector.getInstance(AutomationSecretAccessResource.class));
        jersey.register(injector.getInstance(StatusResource.class));

        ManualStatusHealthCheck mshc = new ManualStatusHealthCheck();
        environment.healthChecks().register("manualStatus", mshc);
        environment.admin().addServlet("manualStatus", new ManualStatusServlet(mshc)).addMapping("/status/*");

        validateDatabase(config);

        logger.debug("Keywhiz configuration complete");
    }

    private void validateDatabase(KeywhizConfig config) {
        logger.debug("Validating database state");
        DataSource dataSource = config.getDataSourceFactory().build(new MetricRegistry(),
                "flyway-validation-datasource");
        Flyway flyway = new Flyway();
        flyway.setDataSource(dataSource);
        flyway.setLocations(config.getMigrationsDir());
        flyway.validate();
    }

    /**
     * Customizes ObjectMapper for common settings.
     *
     * @param objectMapper to be customized
     * @return customized input factory
     */
    public static ObjectMapper customizeObjectMapper(ObjectMapper objectMapper) {
        objectMapper.registerModules(new Jdk8Module());
        objectMapper.registerModules(new JavaTimeModule());
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }
}