Skip to content
This repository has been archived by the owner on Mar 5, 2021. It is now read-only.

RPM signing feature #141

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Web-ContextPath: /yum
Import-Package: com.google.common.escape;version="18.0.0",
com.google.common.net;version="18.0.0",
com.google.common.io;version="18.0.0",
com.google.common.hash;version="18.0.0",
com.google.gson;version="2.3.1",
javax.servlet;version="3.1.0",
javax.servlet.http;version="3.1.0",
org.apache.commons.compress.archivers.cpio;version="1.9.0",
org.bouncycastle.openpgp;version="1.52.0",
org.eclipse.packagedrone;version="1.0.0",
org.eclipse.packagedrone.repo;version="1.0.0",
org.eclipse.packagedrone.repo.aspect;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.aggregate;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.common.spool;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.extract;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.virtual;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.group;version="1.0.0",
org.eclipse.packagedrone.repo.aspect.recipe;version="1.0.0",
org.eclipse.packagedrone.repo.channel;version="1.0.0",
Expand All @@ -28,6 +32,7 @@ Import-Package: com.google.common.escape;version="18.0.0",
org.eclipse.packagedrone.repo.utils;version="1.0.0",
org.eclipse.packagedrone.repo.web.utils;version="1.0.0",
org.eclipse.packagedrone.repo.xml;version="1.0.0",
org.eclipse.packagedrone.utils;version="1.0.0",
org.eclipse.packagedrone.utils.io;version="1.0.0",
org.eclipse.packagedrone.utils.rpm;version="0.13.0",
org.eclipse.packagedrone.utils.rpm.deps;version="0.13.0",
Expand All @@ -43,7 +48,7 @@ Import-Package: com.google.common.escape;version="18.0.0",
org.osgi.framework;version="1.8.0",
org.osgi.util.tracker;version="1.5.1",
org.slf4j;version="1.7.2"
Service-Component: OSGI-INF/rpm.xml,OSGI-INF/yum.xml,OSGI-INF/groupRpm.xml,OSGI-INF/recipeYum.xml,
Service-Component: OSGI-INF/rpm.xml,OSGI-INF/rpmSign.xml,OSGI-INF/yum.xml,OSGI-INF/groupRpm.xml,OSGI-INF/recipeYum.xml,
OSGI-INF/servlet.xml
Require-Bundle: org.jboss.spec.javax.servlet.jstl.jboss-jstl-api_1.2_spec;bundle-version="1.1.2"
Export-Package: org.eclipse.packagedrone.repo.adapter.rpm;version="1.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
drone.aspect.id=rpm.signer
drone.aspect.name=RPM Signer
drone.aspect.description=Sign RPM files
drone.aspect.version=1.0.0
drone.aspect.group.id=rpm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.packagedrone.repo.adapter.rpm.signer">
<implementation class="org.eclipse.packagedrone.repo.adapter.rpm.internal.RpmSignerAspectFactory"/>
<properties entry="OSGI-INF/rpmSign.properties"/>
<service>
<provide interface="org.eclipse.packagedrone.repo.aspect.ChannelAspectFactory"/>
</service>
</scr:component>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
* Walker Funk - Trident Systems Inc. - rpm signing components
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.rpm;

Expand All @@ -18,8 +19,12 @@ public final class Constants

public static final String RPM_ASPECT_ID = "rpm";

public static final String RPM_SIGN_ASPECT_ID = "rpm.signer";

public static final String YUM_ASPECT_ID = "yum";

public static final MetaKey KEY_RSA = new MetaKey ( GROUP_ID, "rsa" );

public static final MetaKey KEY_INFO = new MetaKey ( RPM_ASPECT_ID, "info" );

private Constants ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
* Bachmann electronic GmbH - #86 Adding 'release' rpm metadata tag
* Walker Funk - Trident Systems Inc. rpm rsa signature extraction
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.rpm.internal;

Expand All @@ -21,6 +22,7 @@
import org.eclipse.packagedrone.repo.adapter.rpm.RpmInformationsJson;
import org.eclipse.packagedrone.repo.aspect.extract.Extractor;
import org.eclipse.packagedrone.utils.rpm.RpmTag;
import org.eclipse.packagedrone.utils.rpm.RpmSignatureTag;
import org.eclipse.packagedrone.utils.rpm.info.RpmInformation;
import org.eclipse.packagedrone.utils.rpm.info.RpmInformations;
import org.eclipse.packagedrone.utils.rpm.parse.RpmInputStream;
Expand Down Expand Up @@ -54,6 +56,12 @@ public void extractMetaData ( final Context context, final Map<String, String> m
metadata.put ( "release", RpmInformations.asString ( in.getPayloadHeader ().getTag ( RpmTag.RELEASE ) ) );

metadata.put ( Constants.KEY_INFO.getKey (), RpmInformationsJson.toJson ( info ) );

String signature = RpmInformations.asArmored ( in.getSignatureHeader ().getTag ( RpmSignatureTag.RSAHEADER ) );
if ( signature != null && signature != "" )
{
metadata.put ( Constants.KEY_RSA.getKey (), signature );
}
}
catch ( final Exception e )
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2019 Trident Systems, Inc.
* This software was developed with U.S government funding in support of the above
* contract. Trident grants unlimited rights to modify, distribute and incorporate
* our contributions to Eclipse Package Drone bound by the overall restrictions from
* the parent Eclipse Public License v1.0 available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Walker Funk - Trident Systems Inc. - initial implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.rpm.internal;

import org.eclipse.packagedrone.repo.aspect.ChannelAspect;
import org.eclipse.packagedrone.repo.aspect.ChannelAspectFactory;
import org.eclipse.packagedrone.repo.aspect.virtual.Virtualizer;
import org.eclipse.packagedrone.repo.adapter.rpm.Constants;
import org.eclipse.packagedrone.repo.adapter.rpm.internal.RpmSignerVirtualizer;

public class RpmSignerAspectFactory implements ChannelAspectFactory
{

@Override
public ChannelAspect createAspect ()
{
return new ChannelAspect () {

@Override
public String getId ()
{
return Constants.RPM_SIGN_ASPECT_ID;
}

@Override
public Virtualizer getArtifactVirtualizer ()
{
return new RpmSignerVirtualizer ();
}
};
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*******************************************************************************
* Copyright (c) 2019 Trident Systems, Inc.
* This software was developed with U.S government funding in support of the above
* contract. Trident grants unlimited rights to modify, distribute and incorporate
* our contributions to Eclipse Package Drone bound by the overall restrictions from
* the parent Eclipse Public License v1.0 available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Walker Funk - Trident Systems Inc. - initial implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.rpm.internal;

import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.HashMap;
import java.util.Collection;

import org.eclipse.packagedrone.repo.MetaKey;
import org.eclipse.packagedrone.repo.utils.HashHelper;
import org.eclipse.packagedrone.repo.signing.SigningService;
import org.eclipse.packagedrone.repo.aspect.virtual.Virtualizer;
import org.eclipse.packagedrone.repo.channel.ArtifactInformation;
import org.eclipse.packagedrone.repo.adapter.rpm.Constants;
import org.eclipse.packagedrone.repo.adapter.rpm.yum.internal.YumChannelAggregator;
import org.eclipse.packagedrone.utils.Exceptions;
import org.eclipse.packagedrone.utils.rpm.parse.RpmParserStream;

import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import com.google.common.io.ByteStreams;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RpmSignerVirtualizer implements Virtualizer
{
private final static Logger logger = LoggerFactory.getLogger ( RpmSignerVirtualizer.class );

private static final MetaKey KEY_SIGNING_ID = new MetaKey ( "yum", "signingServiceId" );

private final BundleContext bundleContext = FrameworkUtil.getBundle ( YumChannelAggregator.class ).getBundleContext ();

@Override
public void virtualize ( final Context context )
{
Exceptions.wrapException ( () -> processVirtualize ( context ) );
}

private void processVirtualize ( final Context context ) throws Exception
{
final Path path = context.getFile ();
final ArtifactInformation art = context.getArtifactInformation ();
final String name = art.getName ();
Map<MetaKey, String> metaData = new HashMap<> ( art.getMetaData () );

if ( metaData.containsKey ( Constants.KEY_RSA ) )
{
return;
}

final String signingServiceId = context.getProvidedChannelMetaData ().get ( KEY_SIGNING_ID );
ServiceReference<SigningService> ssref = null;
SigningService signingService = null;

if ( signingServiceId != null && !signingServiceId.isEmpty () )
{
final Collection<ServiceReference<SigningService>> services = bundleContext.getServiceReferences ( SigningService.class, String.format( "(%s=%s)", org.osgi.framework.Constants.SERVICE_PID, signingServiceId ) );

if ( services == null || services.isEmpty () )
{
throw new IllegalStateException ( String.format ( "Unable to find configured signing service: %s", signingServiceId ) );
}

ssref = services.iterator ().next ();
signingService = bundleContext.getService ( ssref );

try ( RpmParserStream preIn = new RpmParserStream ( new BufferedInputStream ( Files.newInputStream ( path, StandardOpenOption.READ ) ) ); )
{
signingService.signRpm ( path, preIn );

Map<String, HashFunction> functions = new HashMap<> ();

functions.put ( "md5", Hashing.md5 () );
functions.put ( "sha1", Hashing.sha1 () );
functions.put ( "sha256", Hashing.sha256 () );
functions.put ( "sha512", Hashing.sha512 () );

final Map<String, HashCode> result = HashHelper.createChecksums ( path, functions );
for ( final Map.Entry<String, HashCode> entry : result.entrySet () )
{
metaData.replace ( new MetaKey ("hasher", entry.getKey () ), entry.getValue ().toString () );
}

DataInputStream postIn = new DataInputStream ( Files.newInputStream( path, StandardOpenOption.READ ) );
context.createVirtualArtifact ( name, out -> ByteStreams.copy ( postIn, out ), metaData );
}
catch ( final Exception e )
{
logger.debug ( "Failed to sign RPM", e );
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
* Walker Funk - Trident Systems Inc. - limit repo to only signed rpms when signing enabled
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.rpm.yum.internal;

Expand Down Expand Up @@ -46,6 +47,8 @@ public class YumChannelAggregator implements ChannelAggregator

private final XmlToolsFactory xml;

private boolean isSigning = false;

public YumChannelAggregator ( final XmlToolsFactory xml )
{
this.xml = xml;
Expand All @@ -69,6 +72,7 @@ public Map<String, String> aggregateMetaData ( final AggregationContext context

ssref = services.iterator ().next ();
signingService = this.context.getService ( ssref );
this.isSigning = true;
}

try
Expand All @@ -88,20 +92,22 @@ public Map<String, String> aggregateMetaData ( final AggregationContext context
creator.process ( repoContext -> {
for ( final ArtifactInformation art : context.getArtifacts () )
{
final RpmInformation info = RpmInformationsJson.fromJson ( art.getMetaData ().get ( Constants.KEY_INFO ) );

if ( info == null )
if ( ( this.isSigning && art.getMetaData ().containsKey ( Constants.KEY_RSA ) ) || !this.isSigning )
{
continue;
}
final RpmInformation info = RpmInformationsJson.fromJson(art.getMetaData().get(Constants.KEY_INFO));

final String sha1 = art.getMetaData ().get ( KEY_SHA1 );
final Map<HashAlgorithm, String> checksums = Collections.singletonMap ( HashAlgorithm.SHA1, sha1 );
if (info == null) {
continue;
}

final String location = String.format ( "pool/%s/%s", art.getId (), art.getName () );
final RepositoryCreator.FileInformation file = new RepositoryCreator.FileInformation ( art.getCreationInstant (), art.getSize (), location );
final String sha1 = art.getMetaData().get(KEY_SHA1);
final Map<HashAlgorithm, String> checksums = Collections.singletonMap(HashAlgorithm.SHA1, sha1);

repoContext.addPackage ( file, info, checksums, HashAlgorithm.SHA1 );
final String location = String.format("pool/%s/%s", art.getId(), art.getName());
final RepositoryCreator.FileInformation file = new RepositoryCreator.FileInformation(art.getCreationInstant(), art.getSize(), location);

repoContext.addPackage(file, info, checksums, HashAlgorithm.SHA1);
}
}
} );

Expand Down Expand Up @@ -134,4 +140,4 @@ private DefaultXmlContext makeXmlContext ()
final DefaultXmlContext xmlCtx = new DefaultXmlContext ( dbf, this.xml.newTransformerFactory () );
return xmlCtx;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class YumRecipe implements Recipe
@Override
public LinkTarget setup ( final String channelId, final AspectableChannel channel )
{
channel.addAspects ( true, "rpm", "yum" );
channel.addAspects ( true, "rpm", "yum", "rpm.signer" );
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
* Walker Funk - Trident Systems Inc. - added system call to clear function to delete empty directories
*******************************************************************************/
package org.eclipse.packagedrone.repo.channel.apm;

Expand All @@ -30,6 +31,7 @@
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.lang.Runtime;

import org.eclipse.packagedrone.repo.MetaKey;
import org.eclipse.packagedrone.repo.channel.ArtifactInformation;
Expand Down Expand Up @@ -822,6 +824,16 @@ public void clear ()

this.state.setNumberOfArtifacts ( 0L );
this.state.setNumberOfBytes ( 0L );

final String cmd = "rm -rf " + System.getProperty ( "drone.storage.base" ) + "/channels/" + this.channelId + "/blobs/data/*";
try
{
Process p = Runtime.getRuntime().exec( new String[] {"sh", "-c", cmd} );
}
catch ( Exception e )
{
throw new RuntimeException ( "Could not remove channel " + this.channelId + " data directories" );
}
}

@Override
Expand Down
Loading