/************************************************************************* * Copyright 2009-2015 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. * * This file may incorporate work covered under the following copyright * and permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, * with or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL, * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE, * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS. ************************************************************************/ package com.eucalyptus.empyrean; import static com.eucalyptus.util.Parameters.checkParam; import static org.hamcrest.Matchers.notNullValue; import java.nio.charset.StandardCharsets; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import javax.annotation.Nullable; import com.eucalyptus.component.ServiceOrderings; import com.eucalyptus.component.annotation.ComponentNamed; import com.eucalyptus.component.groups.ServiceGroups; import com.eucalyptus.crypto.Digest; import com.eucalyptus.crypto.util.PEMFiles; import com.eucalyptus.util.fsm.OrderlyTransitionException; import com.google.common.base.Functions; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.apache.log4j.Logger; import com.eucalyptus.component.Component; import com.eucalyptus.component.ComponentId; import com.eucalyptus.component.ComponentIds; import com.eucalyptus.component.Components; import com.eucalyptus.component.Partitions; import com.eucalyptus.component.ServiceConfiguration; import com.eucalyptus.component.ServiceConfigurations; import com.eucalyptus.component.Topology; import com.eucalyptus.component.annotation.ServiceOperation; import com.eucalyptus.context.Contexts; import com.eucalyptus.records.Logs; import com.eucalyptus.util.EucalyptusCloudException; import com.eucalyptus.util.Exceptions; import com.eucalyptus.util.Internets; import com.eucalyptus.util.TypeMappers; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.io.BaseEncoding; @ComponentNamed public class EmpyreanService { private static Logger LOG = Logger.getLogger( EmpyreanService.class ); @ServiceOperation( hostDispatch = true ) public enum ModifyService implements Function<ModifyServiceType, ModifyServiceResponseType> { INSTANCE; @Override public ModifyServiceResponseType apply( final ModifyServiceType input ) { try { return EmpyreanService.modifyService( input ); } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } } @ServiceOperation( hostDispatch = true ) public enum StartService implements Function<StartServiceType, StartServiceResponseType> { INSTANCE; @Override public StartServiceResponseType apply( final StartServiceType input ) { try { return EmpyreanService.startService( input ); } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } } @ServiceOperation( hostDispatch = true ) public enum StopService implements Function<StopServiceType, StopServiceResponseType> { INSTANCE; @Override public StopServiceResponseType apply( final StopServiceType input ) { try { return EmpyreanService.stopService( input ); } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } } @ServiceOperation( hostDispatch = true ) public enum EnableService implements Function<EnableServiceType, EnableServiceResponseType> { INSTANCE; @Override public EnableServiceResponseType apply( final EnableServiceType input ) { try { return EmpyreanService.enableService( input ); } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } } @ServiceOperation( hostDispatch = true ) public enum DisableService implements Function<DisableServiceType, DisableServiceResponseType> { INSTANCE; @Override public DisableServiceResponseType apply( final DisableServiceType input ) { try { return EmpyreanService.disableService( input ); } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } } enum NamedTransition implements Predicate<ModifyServiceType> { INSTANCE; @Override public boolean apply( ModifyServiceType request ) { try { final Topology.Transitions transition = Topology.Transitions.valueOf( request.getState( ).toUpperCase( ) ); String name = request.getName( ); ServiceConfiguration config = findService( name ); if ( Topology.Transitions.RESTART.equals( transition ) ) { Topology.stop( config ).get( ); try { Topology.start( config ).get( ); } catch ( Exception ex ) { Exceptions.maybeInterrupted( ex ); Logs.extreme( ).error( ex, ex ); throw Exceptions.toUndeclared( ex ); } } else { Topology.transition( transition.get( ) ).apply( config ).get( ); } } catch ( final IllegalArgumentException ex ) { return false; } catch ( final Exception ex ) { Exceptions.maybeInterrupted( ex ); Logs.extreme( ).error( ex, ex ); throw Exceptions.toUndeclared( ex ); } return true; } } private static ServiceConfiguration findService( final String name ) { checkParam( name, notNullValue() ); Predicate<ServiceConfiguration> nameOrFullName = new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( ServiceConfiguration input ) { return name.equals( input.getName( ) ) || name.equals( input.getFullName( ).toString( ) ); } }; for ( final ComponentId compId : ComponentIds.list( ) ) { ServiceConfiguration a; try { return Iterables.find( Components.lookup( compId ).services( ), nameOrFullName ); } catch ( NoSuchElementException ex ) { if ( compId.isRegisterable( ) ) { try { return ServiceConfigurations.lookupByName( compId.getClass( ), name ); } catch ( Exception ex1 ) {} } } } throw new NoSuchElementException( "Failed to lookup service named: " + name ); } public static ModifyServiceResponseType modifyService( final ModifyServiceType request ) throws Exception { final ModifyServiceResponseType reply = request.getReply( ); try { if ( NamedTransition.INSTANCE.apply( request ) ) { reply.markWinning( ); } else { Component.State nextState = Component.State.valueOf( request.getState( ).toUpperCase( ) ); ServiceConfiguration config = findService( request.getName( ) ); Topology.transition( nextState ).apply( config ).get( ); reply.markWinning( ); } } catch ( Exception ex ) { Exceptions.maybeInterrupted( ex ); throw new EucalyptusCloudException( "Failed to execute request transition: " + request.getState( ) + "\nDue to:\n" + Throwables.getRootCause( ex ).getMessage( ) + "\nPossible arguments are: \n" + "TRANSITIONS\n\t" + Joiner.on( "\n\t" ).join( Topology.Transitions.values( ) ) + "STATES\n\t" + Joiner.on( "\n\t" ).join( Component.State.values( ) ), ex ); } return reply; } public static StartServiceResponseType startService( final StartServiceType request ) throws Exception { final StartServiceResponseType reply = request.getReply( ); for ( final ServiceId serviceInfo : request.getServices( ) ) { try { final Component comp = Components.lookup( serviceInfo.getType( ) ); final ServiceConfiguration service = TypeMappers.transform( serviceInfo, ServiceConfiguration.class ); if ( service.isVmLocal( ) ) { try { Topology.start( service ).get( ); reply.getServices( ).add( serviceInfo ); } catch ( final IllegalStateException ex ) { LOG.error( ex, ex ); throw ex; } } } catch ( final Exception ex ) { final OrderlyTransitionException otex = Exceptions.findCause( ex, OrderlyTransitionException.class ); if ( otex != null ) { LOG.info( otex ); } else { LOG.error( ex, ex ); } throw ex; } } return reply; } public static DestroyServiceResponseType destroyService( final DestroyServiceType request ) throws Exception { DestroyServiceResponseType reply = request.getReply( ); for ( final ServiceId serviceInfo : request.getServices( ) ) { try { final ServiceConfiguration service = TypeMappers.transform( serviceInfo, ServiceConfiguration.class ); if ( service.isVmLocal( ) ) { try { Topology.destroy( service ).get( ); } catch ( final IllegalStateException ex ) { LOG.error( ex, ex ); } } reply.getServices( ).add( serviceInfo ); } catch ( final Exception ex ) { LOG.error( ex ); Logs.extreme( ).debug( ex, ex ); } } return reply; } public static StopServiceResponseType stopService( final StopServiceType request ) throws Exception { final StopServiceResponseType reply = request.getReply( ); for ( final ServiceId serviceInfo : request.getServices( ) ) { try { final Component comp = Components.lookup( serviceInfo.getType( ) ); final ServiceConfiguration service = TypeMappers.transform( serviceInfo, ServiceConfiguration.class ); if ( service.isVmLocal( ) ) { try { Topology.stop( service ).get( ); reply.getServices( ).add( serviceInfo ); } catch ( final IllegalStateException ex ) { LOG.error( ex, ex ); throw ex; } } } catch ( final Exception ex ) { LOG.error( ex, ex ); throw ex; } } return reply; } public static EnableServiceResponseType enableService( final EnableServiceType request ) throws Exception { final EnableServiceResponseType reply = request.getReply( ); for ( final ServiceId serviceInfo : request.getServices( ) ) { try { final Component comp = Components.lookup( serviceInfo.getType( ) ); final ServiceConfiguration service = TypeMappers.transform( serviceInfo, ServiceConfiguration.class ); if ( service.isVmLocal( ) ) { try { Topology.enable( service ).get( ); reply.getServices( ).add( serviceInfo ); } catch ( final IllegalStateException ex ) { LOG.error( ex, ex ); throw ex; } } } catch ( final Exception ex ) { LOG.error( ex, ex ); throw ex; } } return reply; } public static DisableServiceResponseType disableService( final DisableServiceType request ) throws Exception { final DisableServiceResponseType reply = request.getReply( ); for ( final ServiceId serviceInfo : request.getServices( ) ) { try { final Component comp = Components.lookup( serviceInfo.getType( ) ); final ServiceConfiguration service = TypeMappers.transform( serviceInfo, ServiceConfiguration.class ); if ( service.isVmLocal( ) ) { try { Topology.disable( service ).get( ); reply.getServices( ).add( serviceInfo ); } catch ( final IllegalStateException ex ) { LOG.error( ex, ex ); throw ex; } } } catch ( final NoSuchElementException ex ) { LOG.error( ex, ex ); throw ex; } } return reply; } static class Filters { /** * Build a predicate from the given filters */ private static Predicate<ServiceConfiguration> from( Iterable<Filter> filters ) { final List<Predicate<ServiceConfiguration>> predicates = Lists.newArrayList( ); for ( final Filter filter : filters ) { final Function<String,Predicate<ComponentId>> cbuilder = componentIdFilterBuilders.get( filter.getName( ) ); if ( cbuilder != null ) { predicates.add( Predicates.compose( Predicates.or( Iterables.transform( filter.getValues( ), cbuilder ) ), ServiceConfigurations.componentId( ) ) ); } else { final Function<String, Predicate<ServiceConfiguration>> builder = serviceConfigurationFilterBuilders.get( filter.getName( ) ); predicates.add( builder == null || filter.getValues( ) == null ? Predicates.<ServiceConfiguration>alwaysFalse( ) : Predicates.or( Iterables.transform( filter.getValues( ), builder ) ) ); } } return Predicates.and( predicates ); } /** * Build a predicate from the given filters */ private static Predicate<ComponentId> componentFrom( Iterable<Filter> filters ) { final List<Predicate<ComponentId>> predicates = Lists.newArrayList( ); for ( final Filter filter : filters ) { final Function<String,Predicate<ComponentId>> builder = componentIdFilterBuilders.get( filter.getName( ) ); predicates.add( builder == null || filter.getValues( ) == null ? Predicates.<ComponentId>alwaysFalse( ) : Predicates.or( Iterables.transform( filter.getValues( ), builder ) ) ); } return Predicates.and( predicates ); } private static Predicate<String> usageFrom( Iterable<Filter> filters ) { final List<Predicate<String>> predicates = Lists.newArrayList( ); for ( final Filter filter : filters ) { if ( "certificate-usage".equals( filter.getName( ) ) ) { predicates.add( Predicates.in( filter.getValues( ) ) ); } } return Predicates.and( predicates ); } /** * Create a string filter builder */ private static <I> Function<String,Predicate<I>> sfb( final Function<I,String> f ) { return new Function<String,Predicate<I>>( ) { @Nullable @Override public final Predicate<I> apply( final String filter ) { return new Predicate<I>( ){ @Override public boolean apply( final I item ) { return filter.equals( f.apply( item ) ); } }; } }; }; /** * Create a string set filter builder */ private static <I> Function<String,Predicate<I>> ssfb( final Function<I,Set<String>> f ) { return new Function<String,Predicate<I>>( ) { @Nullable @Override public final Predicate<I> apply( final String filter ) { return new Predicate<I>( ){ @Override public boolean apply( final I item ) { //noinspection ConstantConditions return f.apply( item ).contains( filter ); } }; } }; }; /** * Create a boolean filter builder */ private static <I> Function<String,Predicate<I>> bfb( final Function<I,Boolean> f ) { return sfb( Functions.compose( Functions.toStringFunction( ), f ) ); } /** * Map of filter names to component filter builders */ private static final Map<String,Function<String,Predicate<ComponentId>>> componentIdFilterBuilders = ImmutableMap.<String,Function<String,Predicate<ComponentId>>>builder( ) .put( "internal", bfb( new Function<ComponentId, Boolean>( ) { @Override public Boolean apply( final ComponentId componentId ) { return componentId.isInternal( ); } } ) ) .put( "user-service", bfb( new Function<ComponentId, Boolean>( ) { @Override public Boolean apply( final ComponentId componentId ) { return componentId.isAdminService( ); } } ) ) .put( "public", bfb( new Function<ComponentId, Boolean>( ) { @Override public Boolean apply( final ComponentId componentId ) { return componentId.isPublicService( ); } } ) ) .put( "service-type", sfb( ComponentIds.name( ) ) ) .put( "service-group", ssfb( new Function<ComponentId, Set<String>>( ) { @Nullable @Override public Set<String> apply( final ComponentId componentId ) { return Sets.newHashSet( Iterables.transform( ServiceGroups.listMembership( componentId ), ComponentIds.name( ) ) ); } } ) ) .put( "service-group-member", bfb( new Function<ComponentId, Boolean>( ) { @Override public Boolean apply( final ComponentId componentId ) { return !ServiceGroups.listMembership( componentId ).isEmpty( ); } } ) ) .put( "certificate-usage", ssfb( new Function<ComponentId, Set<String>>( ) { @Override public Set<String> apply( final ComponentId componentId ) { return componentId.getCertificateUsages( ); } } ) ) .build( ); /** * Map of filter names to service configuration filter builders */ private static final Map<String,Function<String,Predicate<ServiceConfiguration>>> serviceConfigurationFilterBuilders = ImmutableMap.<String,Function<String,Predicate<ServiceConfiguration>>>builder( ) .put( "host", sfb( new Function<ServiceConfiguration, String>( ) { @Override public String apply( final ServiceConfiguration serviceConfiguration ) { return serviceConfiguration.getHostName( ); } } ) ) .put( "state", new Function<String,Predicate<ServiceConfiguration>>( ){ @Nullable @Override public Predicate<ServiceConfiguration> apply( final String filter ) { return state( Component.State.valueOf( filter.toUpperCase( ) ) ); } } ) .put( "partition", sfb( new Function<ServiceConfiguration, String>( ) { @Override public String apply( final ServiceConfiguration serviceConfiguration ) { return serviceConfiguration.getPartition( ); } } ) ) .build( ); static Predicate<ServiceConfiguration> publicService( ) { return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { return input.getComponentId( ).isPublicService( ); } }; } static Predicate<ServiceConfiguration> partition( final String partition ) { return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { return ( partition == null ) || partition.equals( input.getPartition( ) ); } }; } static Predicate<ServiceConfiguration> host( final String host ) { return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { return ( host == null ) || host.equals( input.getHostName( ) ); } }; } static Predicate<ServiceConfiguration> name( final List<String> names ) { return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { return ( names == null ) || names.isEmpty( ) || names.contains( input.getName() ) || names.contains( input.getFullName().toString() ); } }; } static Predicate<ServiceConfiguration> state( final Component.State state ) { return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { try { return input.lookupState( ).equals( state ); } catch ( final Exception ex ) { return false; } } }; } static Predicate<Component> componentType( final ComponentId compId ) { return new Predicate<Component>( ) { @Override public boolean apply( final Component input ) { return Empyrean.class.equals( compId.getClass( ) ) || input.getComponentId( ).equals( compId ); } }; } static Predicate<ServiceConfiguration> listAllOrInternal( final Boolean listAllArg, final Boolean listUserServicesArg, final Boolean listInternalArg ) { final boolean listAll = Boolean.TRUE.equals( listAllArg ); final boolean listInternal = Boolean.TRUE.equals( listInternalArg ); final boolean listUserServices = Boolean.TRUE.equals( listUserServicesArg ); return new Predicate<ServiceConfiguration>( ) { @Override public boolean apply( final ServiceConfiguration input ) { if ( listAll ) { return true; } else if ( input.getComponentId( ).isDistributedService( ) || Empyrean.class.equals( input.getComponentId( ).getClass() ) ) { return true; } else if ( input.getComponentId( ).isPublicService( ) ) { return Internets.testLocal( input.getHostName( ) ); } else if ( input.getComponentId( ).isAdminService( ) && listUserServices ) { return Internets.testLocal( input.getHostName( ) ); } else if ( input.getComponentId( ).isInternal( ) && listInternal ) { return Internets.testLocal( input.getHostName( ) ); } else { return false; } } }; } } @ServiceOperation( user = true, hostDispatch = true ) public enum DescribeService implements Function<DescribeServicesType, DescribeServicesResponseType> { INSTANCE; @Override public DescribeServicesResponseType apply( final DescribeServicesType input ) { try { if ( !Contexts.lookup( ).isAdministrator() ) { return user( input ); } else { return EmpyreanService.describeService( input ); } } catch ( final Exception ex ) { throw Exceptions.toUndeclared( ex ); } } public DescribeServicesResponseType user( final DescribeServicesType request ) { final DescribeServicesResponseType reply = request.getReply( ); /** * Only show public services to normal users. * Allow for filtering by component and state w/in that set. */ final List<Predicate<ServiceConfiguration>> filters = new ArrayList<Predicate<ServiceConfiguration>>( ) { { this.add( Filters.from( request.getFilters( ) ) ); this.add( Filters.publicService( ) ); if ( request.getByPartition( ) != null ) { this.add( Filters.partition( request.getByPartition( ) ) ); } if ( request.getByState( ) != null ) { this.add( Filters.state( Component.State.valueOf( request.getByState( ).toUpperCase( ) ) ) ); } } }; final Predicate<Component> componentFilter = ( Predicate<Component> ) ( request.getByServiceType( ) != null ? Filters.componentType( ComponentIds.lookup( request.getByServiceType( ).toLowerCase( ) ) ) : Predicates.alwaysTrue( ) ); final Predicate<ServiceConfiguration> configPredicate = Predicates.and( filters ); final Collection<ServiceConfiguration> replyConfigs = Lists.newArrayList(); for ( final Component comp : Iterables.filter( Components.list( ), componentFilter ) ) { replyConfigs.addAll( Collections2.filter( comp.services( ), configPredicate ) ); } final ImmutableList<ServiceConfiguration> sortedReplyConfigs = ServiceOrderings.defaultOrdering().immutableSortedCopy( replyConfigs ); final Collection<ServiceStatusType> replyStatuses = Collections2.transform( sortedReplyConfigs, ServiceConfigurations.asServiceStatus( false, false ) ); reply.getServiceStatuses().addAll( replyStatuses ); return reply; } } public static DescribeServicesResponseType describeService( final DescribeServicesType request ) { final DescribeServicesResponseType reply = request.getReply( ); Topology.touch( request ); if ( request.getServices( ).isEmpty( ) ) { final ComponentId compId = ( request.getByServiceType( ) != null ) ? ComponentIds.lookup( request.getByServiceType( ).toLowerCase( ) ) : Empyrean.INSTANCE; final boolean showEventStacks = Boolean.TRUE.equals( request.getShowEventStacks( ) ); final boolean showEvents = Boolean.TRUE.equals( request.getShowEvents( ) ) || showEventStacks; final Function<ServiceConfiguration, ServiceStatusType> transformToStatus = ServiceConfigurations.asServiceStatus( showEvents, showEventStacks ); final List<Predicate<ServiceConfiguration>> filters = new ArrayList<Predicate<ServiceConfiguration>>( ) { { this.add( Filters.from( request.getFilters( ) ) ); if ( request.getByPartition( ) != null ) { Partitions.exists( request.getByPartition( ) ); this.add( Filters.partition( request.getByPartition( ) ) ); } if ( request.getByState( ) != null ) { final Component.State stateFilter = Component.State.valueOf( request.getByState( ).toUpperCase( ) ); this.add( Filters.state( stateFilter ) ); } if ( !request.getServiceNames( ).isEmpty( ) ) { this.add( Filters.name( request.getServiceNames( ) ) ); } this.add( Filters.host( request.getByHost( ) ) ); this.add( Filters.listAllOrInternal( request.getListAll( ), request.getListUserServices( ), request.getListInternal( ) ) ); } }; final Predicate<Component> componentFilter = Filters.componentType( compId ); final Predicate<ServiceConfiguration> configPredicate = Predicates.and( filters ); List<ServiceConfiguration> replyConfigs = Lists.newArrayList(); for ( final Component comp : Components.list( ) ) { if ( componentFilter.apply( comp ) ) { Collection<ServiceConfiguration> acceptedConfigs = Collections2.filter( comp.services(), configPredicate ); replyConfigs.addAll( acceptedConfigs ); } } ImmutableList<ServiceConfiguration> sortedReplyConfigs = ServiceOrderings.defaultOrdering().immutableSortedCopy( replyConfigs ); final Collection<ServiceStatusType> transformedReplyConfigs = Collections2.transform( sortedReplyConfigs, transformToStatus ); reply.getServiceStatuses( ).addAll( transformedReplyConfigs ); } else { for ( ServiceId s : request.getServices( ) ) { reply.getServiceStatuses( ).add( TypeMappers.transform( s, ServiceStatusType.class ) ); } } return reply; } @ServiceOperation( user = true, hostDispatch = true ) public enum DescribeServiceCertificates implements Function<DescribeServiceCertificatesType, DescribeServiceCertificatesResponseType> { INSTANCE; @Override public DescribeServiceCertificatesResponseType apply( final DescribeServiceCertificatesType request ) { final DescribeServiceCertificatesResponseType reply = request.getReply( ); /** * Only show public services to normal users. * Allow for filtering by component and state w/in that set. */ final Predicate<ServiceConfiguration> configPredicate = Filters.publicService( ); final List<ServiceCertificateType> serviceCertificates = Lists.newArrayList( ); final Predicate<Component> componentPredicate = Predicates.compose( Filters.componentFrom( request.getFilters( ) ), Components.componentId( ) ); final Predicate<String> usagePredicate = Filters.usageFrom( request.getFilters( ) ); for ( final Component comp : Iterables.filter( Components.list( ), componentPredicate ) ) { if ( Iterables.any( comp.services( ), Predicates.and( configPredicate, Filters.from( request.getFilters( ) ) ) ) ) { final ComponentId currentComponentId = comp.getComponentId( ); final ServiceCertificateType serviceCertificate = new ServiceCertificateType( ); final Set<String> usages = currentComponentId.getCertificateUsages( ); for ( final String usage : Iterables.filter( usages, usagePredicate ) ) { final X509Certificate certificate = currentComponentId.getCertificate( usage ); try { final byte[] certificateBytes = certificate.getEncoded( ); serviceCertificate.setServiceType( comp.getName( ) ); if ( "der".equals( request.getFormat( ) ) ) { serviceCertificate.setCertificateFormat( "der" ); serviceCertificate.setCertificate( BaseEncoding.base64( ).encode( certificateBytes ) ); } else { serviceCertificate.setCertificateFormat( "pem" ); serviceCertificate.setCertificate( new String( PEMFiles.getBytes( certificate ), StandardCharsets.UTF_8 ) ); } final Digest digest = Digest.forAlgorithm( request.getFingerprintDigest( ) ).or( Digest.SHA256 ); serviceCertificate.setCertificateFingerprintDigest( digest.algorithm( ) ); serviceCertificate.setCertificateFingerprint( BaseEncoding.base16( ).withSeparator( ":", 2 ).encode( digest.digestBinary( certificateBytes ) ) ); serviceCertificate.setCertificateUsage( usage ); serviceCertificates.add( serviceCertificate ); } catch ( final CertificateEncodingException e ) { LOG.error( "Error processing service certificate", e ); } } } } reply.getServiceCertificates( ).addAll( serviceCertificates ); return reply; } } }