/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.service.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import org.candlepin.TestingModules; import org.candlepin.common.config.Configuration; import org.candlepin.model.CertificateSerial; import org.candlepin.model.CertificateSerialCurator; import org.candlepin.model.Consumer; import org.candlepin.model.ConsumerCapability; import org.candlepin.model.ConsumerType; import org.candlepin.model.Content; import org.candlepin.model.Entitlement; import org.candlepin.model.EntitlementCertificate; import org.candlepin.model.EntitlementCertificateCurator; import org.candlepin.model.EntitlementCurator; import org.candlepin.model.Environment; import org.candlepin.model.EnvironmentContent; import org.candlepin.model.KeyPairCurator; import org.candlepin.model.Owner; import org.candlepin.model.Pool; import org.candlepin.model.Product; import org.candlepin.model.ProductContent; import org.candlepin.model.ProductCurator; import org.candlepin.model.dto.ProductContentData; import org.candlepin.model.dto.ProductData; import org.candlepin.model.dto.Subscription; import org.candlepin.pki.PKIUtility; import org.candlepin.pki.X509ByteExtensionWrapper; import org.candlepin.pki.X509ExtensionWrapper; import org.candlepin.pki.impl.BouncyCastlePKIUtility; import org.candlepin.service.ProductServiceAdapter; import org.candlepin.test.TestUtil; import org.candlepin.util.CertificateSizeException; import org.candlepin.util.Util; import org.candlepin.util.X509ExtensionUtil; import org.candlepin.util.X509V3ExtensionUtil; import org.candlepin.util.X509V3ExtensionUtil.HuffNode; import org.candlepin.util.X509V3ExtensionUtil.NodePair; import org.candlepin.util.X509V3ExtensionUtil.PathNode; import com.google.inject.Guice; import com.google.inject.Injector; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.xnap.commons.i18n.I18nFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyPair; import java.security.Security; import java.security.cert.CertificateExpiredException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.zip.InflaterOutputStream; import javax.inject.Inject; /** * DefaultEntitlementCertServiceAdapter */ @SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class DefaultEntitlementCertServiceAdapterTest { @SuppressWarnings("checkstyle:visibilitymodifier") @Rule public ExpectedException thrown = ExpectedException.none(); private static final String CONTENT_LABEL = "label"; private static final String CONTENT_ID = "1234"; private static final String CONTENT_ID_FILE = "2456"; private static final String CONTENT_ID_KICKSTART = "2457"; private static final String CONTENT_ID_UNKNOWN = "2458"; private static final String CONTENT_TYPE = "yum"; private static final String CONTENT_TYPE_KICKSTART = "kickstart"; private static final String CONTENT_TYPE_FILE = "file"; private static final String CONTENT_TYPE_UNKNOWN = "unknown content type"; private static final String CONTENT_GPG_URL = "gpgUrl"; private static final String CONTENT_URL = "/content/dist/rhel/$releasever/$basearch/os"; private static final String CONTENT_URL_UNKNOWN_TYPE = "/unknown/content/type"; private static final String CONTENT_VENDOR = "vendor"; private static final String CONTENT_NAME = "name"; private static final Long CONTENT_METADATA_EXPIRE = 3200L; private static final String ENTITLEMENT_QUANTITY = "10"; private static final String REQUIRED_TAGS = "TAG1,TAG2"; private static final String ARCH_LABEL = "x86_64"; private DefaultEntitlementCertServiceAdapter certServiceAdapter; private X509V3ExtensionUtil v3extensionUtil; @Inject private PKIUtility realPKI; @Inject private EntitlementCurator entCurator; @Inject private Configuration config; @Inject private X509ExtensionUtil extensionUtil; @Mock private CertificateSerialCurator serialCurator; @Mock private KeyPairCurator keyPairCurator; @Mock private PKIUtility mockedPKI; @Mock private ProductServiceAdapter productAdapter; @Mock private ProductCurator productCurator; private Consumer consumer; private Product product; private Product largeContentProduct; private Subscription subscription; private Subscription largeContentSubscription; private Entitlement entitlement; private Entitlement largeContentEntitlement; private Pool pool; private Pool largeContentPool; private Content content; private Content kickstartContent; private Content fileContent; private Content unknownTypeContent; private Content noArchContent; private Owner owner; private Set<Content> superContent; private Set<Content> largeContent; private static KeyPair keyPair; private String[] testUrls = { "/content/dist/rhel/$releasever/$basearch/os", "/content/dist/rhel/$releasever/$basearch/debug", "/content/dist/rhel/$releasever/$basearch/source/SRPMS", "/content/dist/jboss/source", "/content/beta/rhel/$releasever/$basearch/os", "/content/beta/rhel/$releasever/$basearch/debug", "/content/beta/rhel/$releasever/$basearch/source/SRPMS" }; static { Security.addProvider(new BouncyCastleProvider()); } @BeforeClass public static void keyPair() throws Exception { ClassLoader cl = DefaultEntitlementCertServiceAdapterTest.class.getClassLoader(); InputStream keyStream = cl.getResourceAsStream("test.key"); PEMReader reader = null; keyPair = null; try { reader = new PEMReader(new InputStreamReader(keyStream)); keyPair = (KeyPair) reader.readObject(); } finally { if (reader != null) { reader.close(); } } } @Before public void setUp() { Injector injector = Guice.createInjector( new TestingModules.MockJpaModule(), new TestingModules.ServletEnvironmentModule(), new TestingModules.StandardTest() ); injector.injectMembers(this); v3extensionUtil = new X509V3ExtensionUtil(config, entCurator); certServiceAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, extensionUtil, v3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), config, productCurator); product = TestUtil.createProduct("12345", "a product"); product.setAttribute(Product.Attributes.VERSION, "version"); product.setAttribute(Product.Attributes.VARIANT, "variant"); product.setAttribute(Product.Attributes.TYPE, "SVC"); product.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); largeContentProduct = TestUtil.createProduct("67890", "large content product"); largeContentProduct.setAttribute(Product.Attributes.VERSION, "version"); largeContentProduct.setAttribute(Product.Attributes.VARIANT, "variant"); largeContentProduct.setAttribute(Product.Attributes.TYPE, "SVC"); largeContentProduct.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); content = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL); content.setMetadataExpire(CONTENT_METADATA_EXPIRE); content.setRequiredTags(REQUIRED_TAGS); kickstartContent = createContent(CONTENT_NAME, CONTENT_ID_KICKSTART, CONTENT_LABEL, CONTENT_TYPE_KICKSTART, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL); kickstartContent.setMetadataExpire(CONTENT_METADATA_EXPIRE); kickstartContent.setRequiredTags(REQUIRED_TAGS); fileContent = createContent(CONTENT_NAME, CONTENT_ID_FILE, CONTENT_LABEL, CONTENT_TYPE_FILE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL); fileContent.setMetadataExpire(CONTENT_METADATA_EXPIRE); fileContent.setRequiredTags(REQUIRED_TAGS); unknownTypeContent = createContent(CONTENT_NAME, CONTENT_ID_UNKNOWN, CONTENT_LABEL, CONTENT_TYPE_UNKNOWN, CONTENT_VENDOR, CONTENT_URL_UNKNOWN_TYPE, CONTENT_GPG_URL, ARCH_LABEL); unknownTypeContent.setMetadataExpire(CONTENT_METADATA_EXPIRE); unknownTypeContent.setRequiredTags(REQUIRED_TAGS); String emptyArches = ""; noArchContent = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, emptyArches); superContent = new HashSet<Content>(); int index = 0; for (String url : testUrls) { ++index; superContent.add(createContent(CONTENT_NAME + "-" + index, CONTENT_ID + "-" + index, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, url, CONTENT_GPG_URL, ARCH_LABEL)); } largeContent = new HashSet<Content>(); index = 0; for (String url : largeTestUrls) { ++index; largeContent.add(createContent(CONTENT_NAME + "-" + index, CONTENT_ID + "-" + index, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, url, CONTENT_GPG_URL, ARCH_LABEL)); } subscription = TestUtil.createSubscription(null, product, new HashSet<Product>()); subscription.setId("1"); subscription.setQuantity(1L); largeContentSubscription = TestUtil.createSubscription(null, largeContentProduct, new HashSet<Product>()); largeContentSubscription.setId("2"); largeContentSubscription.setQuantity(1L); owner = new Owner(); pool = new Pool(); pool.setQuantity(1L); pool.setProduct(product); pool.setStartDate(subscription.getStartDate()); pool.setEndDate(subscription.getEndDate()); largeContentPool = new Pool(); largeContentPool.setProduct(largeContentProduct); consumer = new Consumer("Test Consumer", "bob", owner, new ConsumerType(ConsumerType.ConsumerTypeEnum.SYSTEM)); consumer.setUuid("test-consumer"); entitlement = new Entitlement(); entitlement.setQuantity(new Integer(ENTITLEMENT_QUANTITY)); entitlement.setConsumer(consumer); entitlement.setPool(pool); entitlement.setOwner(owner); largeContentEntitlement = new Entitlement(); largeContentEntitlement.setQuantity(new Integer(ENTITLEMENT_QUANTITY)); largeContentEntitlement.setConsumer(consumer); largeContentEntitlement.setPool(largeContentPool); largeContentEntitlement.setOwner(owner); product.addContent(content, false); // when(productAdapter.getProductById(eq(product.getOwner()), eq(product.getId()))) // .thenReturn(product); // when(productAdapter.getProductById( // eq(largeContentProduct.getOwner()), eq(largeContentProduct.getId())) // ).thenReturn(largeContentProduct); } private Content createContent(String name, String id, String label, String type, String vendor, String url, String gpgUrl, String arches) { Owner owner = TestUtil.createOwner("Example-Corporation"); Content content = TestUtil.createContent(id, name); content.setLabel(label); content.setType(type); content.setVendor(vendor); content.setContentUrl(url); content.setGpgUrl(gpgUrl); content.setArches(arches); return content; } @Test public void temporaryCertificateForUnmappedGuests() throws Exception { Date now = new Date(); consumer.setCreated(now); pool.setAttribute(Pool.Attributes.UNMAPPED_GUESTS_ONLY, "true"); // Set up an adapter with a real PKIUtil certServiceAdapter = new DefaultEntitlementCertServiceAdapter( realPKI, extensionUtil, v3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), config, productCurator); X509Certificate result = certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); // unmapped guest pools expire in 7 days, 7 * 24 = 168 Date oneHourAfterSevenDays = new Date(now.getTime() + 169 * 60 * 60 * 1000); Date oneHourBeforeSevenDays = new Date(now.getTime() + 167 * 60 * 60 * 1000); result.checkValidity(oneHourBeforeSevenDays); thrown.expect(CertificateExpiredException.class); result.checkValidity(oneHourAfterSevenDays); } @Test public void predateEntitlementCerts() throws Exception { consumer.setCreated(new Date()); // Set up an adapter with a real PKIUtil certServiceAdapter = new DefaultEntitlementCertServiceAdapter( realPKI, extensionUtil, v3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), config, productCurator); // pool start date is more than an hour ago, use it Calendar cal = Calendar.getInstance(); cal.add(Calendar.HOUR, -2); pool.setStartDate(cal.getTime()); X509Certificate result = certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); // cert does not capture the milliseconds. truncating. assertTrue(result.getNotBefore().getTime() == pool.getStartDate().getTime() / 1000 * 1000); // pool start date is less than an hour ago, so an hour gets used cal.add(Calendar.MINUTE, 90); pool.setStartDate(cal.getTime()); result = certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); assertTrue(result.getNotBefore().getTime() < pool.getStartDate().getTime() / 1000 * 1000); } @Test(expected = CertificateSizeException.class) public void tooManyContentSetsAcrossMultipleProducts() throws Exception { Set<Product> providedProducts = new HashSet<Product>(); Product pp1 = new Product("12346", "Provided 1", "variant", "version", ARCH_LABEL, "SVC"); for (Content content : generateContent(100, "PP1")) { pp1.addContent(content, false); } providedProducts.add(pp1); Product pp2 = new Product("12347", "Provided 2", "variant", "version", ARCH_LABEL, "SVC"); for (Content content : generateContent(100, "PP2")) { pp2.addContent(content, false); } providedProducts.add(pp2); // TODO: Is this even needed anymore? // subscription.setProvidedProducts(providedProducts); certServiceAdapter.createX509Certificate(entitlement, product, providedProducts, getProductModels(product, providedProducts, "prefix", entitlement), new BigInteger("1234"), keyPair, true); } private Set<Content> generateContent(int numberToGenerate, String prefix) { Set<Content> productContent = new HashSet<Content>(); for (int i = 0; i < numberToGenerate; i++) { productContent.add(createContent(prefix + CONTENT_NAME + i, prefix + CONTENT_ID + i, prefix + CONTENT_LABEL + i, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL)); } return productContent; } @Test(expected = CertificateSizeException.class) public void tooManyContentSets() throws Exception { Set<Content> productContent = generateContent(X509ExtensionUtil.V1_CONTENT_LIMIT + 1, "TestContent"); product.setProductContent(null); for (Content content : productContent) { product.addContent(content, false); } certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); } @Test public void testContentExtentionCreation() throws CertificateSizeException { Set<X509ExtensionWrapper> contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), null, new HashMap<String, EnvironmentContent>(), entitlement.getConsumer(), product); Map<String, X509ExtensionWrapper> encodedContent = getEncodedContent( contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertTrue(encodedContent.containsKey(CONTENT_METADATA_EXPIRE.toString())); // Nullify this, and make sure it's not there. content.setMetadataExpire(null); contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), "", new HashMap<String, EnvironmentContent>(), entitlement.getConsumer(), product); encodedContent = getEncodedContent(contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertFalse(encodedContent.containsKey(CONTENT_METADATA_EXPIRE.toString())); } @Test public void testContentExtentionIncludesPromotedContent() throws CertificateSizeException { // Environment, with promoted content: Environment e = new Environment("env1", "Env 1", owner); e.getEnvironmentContent().add(new EnvironmentContent(e, content, true)); this.consumer.setEnvironment(e); Map<String, EnvironmentContent> promotedContent = new HashMap<String, EnvironmentContent>(); promotedContent.put(content.getId(), e.getEnvironmentContent().iterator().next()); Set<X509ExtensionWrapper> contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), null, promotedContent, entitlement.getConsumer(), product); Map<String, X509ExtensionWrapper> encodedContent = getEncodedContent( contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertTrue(encodedContent.containsKey(content.getLabel())); } @Test public void testContentRequiredTagsExtention() throws CertificateSizeException { Set<X509ExtensionWrapper> contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), null, new HashMap<String, EnvironmentContent>(), entitlement.getConsumer(), product); Map<String, X509ExtensionWrapper> encodedContent = getEncodedContent( contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertTrue(encodedContent.containsKey(REQUIRED_TAGS.toString())); // Nullify this, and make sure it's not there. content.setRequiredTags(null); contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), "", new HashMap<String, EnvironmentContent>(), entitlement.getConsumer(), product); encodedContent = getEncodedContent(contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertFalse(encodedContent.containsKey(REQUIRED_TAGS.toString())); // Empty string, and make sure it's not there. content.setRequiredTags(""); contentExtensions = extensionUtil.contentExtensions( product.getProductContent(), "", new HashMap<String, EnvironmentContent>(), entitlement.getConsumer(), product); encodedContent = getEncodedContent(contentExtensions); assertTrue(isEncodedContentValid(encodedContent)); assertFalse(encodedContent.containsKey(REQUIRED_TAGS.toString())); } @Test public void testPrefixesShouldBeUsed() throws Exception { owner.setContentPrefix("/somePrefix/"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentUrl("/somePrefix" + CONTENT_URL, CONTENT_ID)), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test @SuppressWarnings("checkstyle:indentation") public void testPrefixExpandsEnvIfConsumerHasOne() throws Exception { owner.setContentPrefix("/someorg/$env/"); // Setup an environment for the consumer: Environment e = new Environment("env1", "Awesome Environment #1", owner); e.getEnvironmentContent().add(new EnvironmentContent(e, content, true)); this.consumer.setEnvironment(e); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat( new ListContainsContentUrl("/someorg/Awesome+Environment+%231" + CONTENT_URL, CONTENT_ID) ), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test @SuppressWarnings("checkstyle:indentation") public void testURLEncoding() throws Exception { owner.setContentPrefix("/some org/$env/"); // Setup an environment for the consumer: Environment e = new Environment("env1", "Awesome Environment #1", owner); e.getEnvironmentContent().add(new EnvironmentContent(e, content, true)); this.consumer.setEnvironment(e); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat( new ListContainsContentUrl("/some+org/Awesome+Environment+%231" + CONTENT_URL, CONTENT_ID) ), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void testPrefixIgnoresEnvIfConsumerHasNone() throws Exception { owner.setContentPrefix("/someorg/$env/"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentUrl("/someorg/$env" + CONTENT_URL, CONTENT_ID)), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void testPrefixesAreNotUsedForUeberCertificate() throws Exception { owner.setContentPrefix("/somePrefix/"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, false); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentUrl(CONTENT_URL, CONTENT_ID)), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void testBlankPrefixesShouldNotEffectAnything() throws Exception { owner.setContentPrefix(""); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentUrl(CONTENT_URL, CONTENT_ID)), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void testNullPrefixesShouldNotEffectAnything() throws Exception { owner.setContentPrefix(null); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentUrl(CONTENT_URL, CONTENT_ID)), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void testFilterProductContent() { Product modProduct = new Product("12345", "a product", "variant", "version", ARCH_LABEL, "SVC"); // Use this set for successful providing queries: Set<Entitlement> successResult = new HashSet<Entitlement>(); successResult.add(new Entitlement()); // just need something in there Content normalContent = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL); // Change label to prevent an equals match: Content modContent = createContent(CONTENT_NAME, CONTENT_ID + "_2", "differentlabel", CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, ARCH_LABEL); modContent.setLabel("mod content"); Set<String> modifiedProductIds = new HashSet<String>( Arrays.asList(new String[]{ "product1", "product2" })); modContent.setModifiedProductIds(modifiedProductIds); modProduct.addContent(normalContent, false); modProduct.addContent(modContent, false); // First check that if we have no entitlements providing the modified // products, // the content set is filtered out: // Mod content should get filtered out because we have no ents providing // the product it modifies: assertEquals(1, extensionUtil.filterProductContent( modProduct, entitlement, entCurator, new HashMap<String, EnvironmentContent>(), false, new HashSet<String>()).size()); // Now mock that we have an entitlement providing one of the modified // products, // and we should see both content sets included in the cert: Set<String> entitledProdIds = new HashSet<String>(); entitledProdIds.add("product2"); assertEquals(2, extensionUtil.filterProductContent( modProduct, entitlement, entCurator, new HashMap<String, EnvironmentContent>(), false, entitledProdIds).size()); // Make sure that we filter by environment when asked. Environment environment = new Environment(); consumer.setEnvironment(environment); Map<String, EnvironmentContent> promotedContent = new HashMap<String, EnvironmentContent>(); promotedContent.put(normalContent.getId(), new EnvironmentContent(environment, normalContent, true)); assertEquals(1, extensionUtil.filterProductContent( modProduct, entitlement, entCurator, promotedContent, true, entitledProdIds).size()); } @Test public void contentExtentionsShouldBeAddedDuringCertificateGeneration() throws Exception { certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsContentExtensions()), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void entitlementQuantityShouldBeAddedDuringCertificateGeneration() throws Exception { certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsEntitlementExtensions()), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void managementDisabledByDefault() throws Exception { certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsProvidesManagement("0")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void managementEnabledByAttribute() throws Exception { pool.getProduct().setAttribute(Product.Attributes.MANAGEMENT_ENABLED, "1"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsProvidesManagement("1")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void stackingIdByAttribute() throws Exception { pool.getProduct().setAttribute(Product.Attributes.STACKING_ID, "3456"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsStackingId("3456")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void virtOnlyByAttribute() throws Exception { //note that "true" gets recoded to "1" to match other bools in the cert entitlement.getPool().setAttribute(Product.Attributes.VIRT_ONLY, "true"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsVirtOnlyKey("1")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void orderNumberAttribute() throws Exception { //note that "true" gets recoded to "1" to match other bools in the cert pool.setOrderNumber("this_order"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsOrderNumberKey("this_order")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void supportValuesPresentOnCertIfAttributePresent() throws Exception { pool.getProduct().setAttribute(Product.Attributes.SUPPORT_LEVEL, "Premium"); pool.getProduct().setAttribute(Product.Attributes.SUPPORT_TYPE, "Level 3"); certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsSupportLevel("Premium")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListContainsSupportType("Level 3")), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void ensureV3CertificateCreationOkWhenConsumerSupportsV3Dot1Certs() throws Exception { Configuration mockConfig = mock(Configuration.class); consumer.setFact("system.certificate_version", "3.3"); subscription.getProduct().setAttribute(Product.Attributes.RAM, "4"); X509V3ExtensionUtil mockV3extensionUtil = mock(X509V3ExtensionUtil.class); X509ExtensionUtil mockExtensionUtil = mock(X509ExtensionUtil.class); DefaultEntitlementCertServiceAdapter entAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, mockExtensionUtil, mockV3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), mockConfig, productCurator); entAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); } @Test public void supportValuesAbsentOnCertIfNoSupportAttributes() throws Exception { certServiceAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListDoesNotContainSupportLevel()), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); verify(mockedPKI).createX509Certificate(any(String.class), argThat(new ListDoesNotContainSupportType()), any(Set.class), any(Date.class), any(Date.class), any(KeyPair.class), any(BigInteger.class), any(String.class)); } @Test public void ensureV3CertIsCreatedWhenEnableCertV3ConfigIsTrue() throws Exception { Configuration mockConfig = mock(Configuration.class); consumer.setFact("system.certificate_version", "3.0"); X509V3ExtensionUtil mockV3extensionUtil = mock(X509V3ExtensionUtil.class); X509ExtensionUtil mockExtensionUtil = mock(X509ExtensionUtil.class); DefaultEntitlementCertServiceAdapter entAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, mockExtensionUtil, mockV3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), mockConfig, productCurator); entAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockV3extensionUtil).getExtensions(eq(entitlement), any(String.class), any(Map.class)); verify(mockV3extensionUtil).getByteExtensions(eq(product), any(List.class), eq(entitlement), any(String.class), any(Map.class)); verifyZeroInteractions(mockExtensionUtil); } @Test public void ensureV3CertIsCreatedWhenV3CapabilityPresent() throws Exception { Configuration mockConfig = mock(Configuration.class); consumer.setType(new ConsumerType(ConsumerType.ConsumerTypeEnum.CANDLEPIN)); Set<ConsumerCapability> set = new HashSet<ConsumerCapability>(); set.add(new ConsumerCapability(consumer, "cert_v3")); consumer.setCapabilities(set); X509V3ExtensionUtil mockV3extensionUtil = mock(X509V3ExtensionUtil.class); X509ExtensionUtil mockExtensionUtil = mock(X509ExtensionUtil.class); DefaultEntitlementCertServiceAdapter entAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, mockExtensionUtil, mockV3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), mockConfig, productCurator); entAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockV3extensionUtil).getExtensions(eq(entitlement), any(String.class), any(Map.class)); verify(mockV3extensionUtil).getByteExtensions(eq(product), any(List.class), eq(entitlement), any(String.class), any(Map.class)); verifyZeroInteractions(mockExtensionUtil); } @Test public void ensureV1CertIsCreatedWhenV3factNotPresent() throws Exception { Configuration mockConfig = mock(Configuration.class); consumer.setType(new ConsumerType(ConsumerType.ConsumerTypeEnum.SYSTEM)); X509V3ExtensionUtil mockV3extensionUtil = mock(X509V3ExtensionUtil.class); X509ExtensionUtil mockExtensionUtil = mock(X509ExtensionUtil.class); DefaultEntitlementCertServiceAdapter entAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, mockExtensionUtil, mockV3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), mockConfig, productCurator); entAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); // Verify v1 verify(mockExtensionUtil).consumerExtensions(eq(consumer)); verifyZeroInteractions(mockV3extensionUtil); } @Test public void ensureV3CertIsCreatedWhenHypervisor() throws Exception { Configuration mockConfig = mock(Configuration.class); consumer.setType(new ConsumerType(ConsumerType.ConsumerTypeEnum.HYPERVISOR)); X509V3ExtensionUtil mockV3extensionUtil = mock(X509V3ExtensionUtil.class); X509ExtensionUtil mockExtensionUtil = mock(X509ExtensionUtil.class); DefaultEntitlementCertServiceAdapter entAdapter = new DefaultEntitlementCertServiceAdapter( mockedPKI, mockExtensionUtil, mockV3extensionUtil, mock(EntitlementCertificateCurator.class), keyPairCurator, serialCurator, entCurator, I18nFactory.getI18n(getClass(), Locale.US, I18nFactory.FALLBACK), mockConfig, productCurator); entAdapter.createX509Certificate(entitlement, product, new HashSet<Product>(), getProductModels(product, new HashSet<Product>(), "prefix", entitlement), new BigInteger("1234"), keyPair, true); verify(mockV3extensionUtil).getExtensions(eq(entitlement), any(String.class), any(Map.class)); verify(mockV3extensionUtil).getByteExtensions(eq(product), any(List.class), eq(entitlement), any(String.class), any(Map.class)); verifyZeroInteractions(mockExtensionUtil); } @Test public void testCleanUpPrefixNoChange() throws Exception { String[] prefixes = {"/", "/some_prefix/", "/some-prefix/", "/some.prefix/", "/Some1Prefix2/"}; for (String prefix : prefixes) { assertEquals(prefix, certServiceAdapter.cleanUpPrefix(prefix)); } } private Boolean extMapHasContentType(Content cont, Map<String, String> extMap, String contentType) { return extMap.containsKey("1.3.6.1.4.1.2312.9.2." + cont.getId() + "." + contentType + ".1"); } private Boolean extMapHasProductBrandType(Product product, Map<String, String> extMap) { return extMap.containsKey("1.3.6.1.4.1.2312.9.1." + product.getId() + "." + "5"); } private Boolean extMapProductBrandTypeMatches(Product product, Map<String, String> extMap, String brandType) { String brandTypeOid = "1.3.6.1.4.1.2312.9.1." + product.getId() + "." + "5"; String extBrandType = extMap.get(brandTypeOid); return extBrandType.equals(brandType); } @Test public void testPrepareV1Extensions() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); products.add(product); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); assertTrue(isEncodedContentValid(map)); assertTrue(map.containsKey(CONTENT_URL)); // do we have a yum content type oid assertTrue(extMapHasContentType(content, extMap, "1")); assertFalse(extMapHasContentType(content, extMap, "2")); } @Test public void testPrepareV1ExtensionsBrandedProduct() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); product.setAttribute(Product.Attributes.BRANDING_TYPE, "os"); products.add(product); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); assertTrue(isEncodedContentValid(map)); assertTrue(extMapHasProductBrandType(product, extMap)); assertTrue(extMapProductBrandTypeMatches(product, extMap, "os")); } @Test public void testPrepareV1ExtensionsNoCompatibleArch() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with no compatible content, but marked as 'ALL' arch Product wrongArchProduct = TestUtil.createProduct("12345", "a product"); wrongArchProduct.setAttribute(Product.Attributes.VERSION, "version"); wrongArchProduct.setAttribute(Product.Attributes.VARIANT, "variant"); wrongArchProduct.setAttribute(Product.Attributes.TYPE, "SVC"); wrongArchProduct.setAttribute(Product.Attributes.ARCHITECTURE, "ALL"); // no x86_64, ie ARCH_LABEL String wrongArches = "s390x,s390,ppc64,ia64"; Content wrongArchContent = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, wrongArches); wrongArchProduct.addContent(wrongArchContent, false); products.add(wrongArchProduct); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); assertFalse(isEncodedContentValid(map)); assertFalse(map.containsKey(CONTENT_URL)); // make sure we don't set content type to "null" assertFalse(extMapHasContentType(kickstartContent, extMap, "null")); } @Test public void testPrepareV1ExtensionsKickstartContent() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with a kickstart content Product kickstartProduct = TestUtil.createProduct("12345", "a product"); kickstartProduct.setAttribute(Product.Attributes.VERSION, "version"); kickstartProduct.setAttribute(Product.Attributes.VARIANT, "variant"); kickstartProduct.setAttribute(Product.Attributes.TYPE, "SVC"); kickstartProduct.setAttribute(Product.Attributes.ARCHITECTURE, "ALL"); kickstartProduct.addContent(kickstartContent, false); products.add(kickstartProduct); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); assertTrue(isEncodedContentValid(map)); assertTrue(map.containsKey(CONTENT_TYPE_KICKSTART)); assertTrue(map.containsKey(CONTENT_URL)); assertFalse(extMapHasContentType(kickstartContent, extMap, "1")); assertFalse(extMapHasContentType(kickstartContent, extMap, "2")); assertTrue(extMapHasContentType(kickstartContent, extMap, "3")); // make sure we don't set content type to "null" assertFalse(extMapHasContentType(kickstartContent, extMap, "null")); } @Test public void testPrepareV1ExtensionsFileContent() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with a kickstart content Product fileProduct = TestUtil.createProduct("12345", "a product"); fileProduct.setAttribute(Product.Attributes.VERSION, "version"); fileProduct.setAttribute(Product.Attributes.VARIANT, "variant"); fileProduct.setAttribute(Product.Attributes.TYPE, "SVC"); fileProduct.setAttribute(Product.Attributes.ARCHITECTURE, "ALL"); fileProduct.addContent(fileContent, false); products.clear(); products.add(fileProduct); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); assertTrue(isEncodedContentValid(map)); assertTrue(map.containsKey(CONTENT_TYPE_FILE)); assertTrue(map.containsKey(CONTENT_URL)); assertFalse(extMapHasContentType(fileContent, extMap, "1")); assertTrue(extMapHasContentType(fileContent, extMap, "2")); assertFalse(extMapHasContentType(fileContent, extMap, "3")); // make sure we don't set content type to "null" assertFalse(extMapHasContentType(fileContent, extMap, "null")); } @Test public void testPrepareV1ExtensionsFileUnknownContentType() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with a kickstart content Product unknownContentTypeProduct = TestUtil.createProduct("12345", "a product"); unknownContentTypeProduct.setAttribute(Product.Attributes.VERSION, "version"); unknownContentTypeProduct.setAttribute(Product.Attributes.VARIANT, "variant"); unknownContentTypeProduct.setAttribute(Product.Attributes.TYPE, "SVC"); unknownContentTypeProduct.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); unknownContentTypeProduct.addContent(unknownTypeContent, false); products.clear(); products.add(unknownContentTypeProduct); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); // we skip content of unknown type for v1 certs assertFalse(isEncodedContentValid(map)); assertFalse(map.containsKey(CONTENT_URL_UNKNOWN_TYPE)); assertFalse(map.containsKey(CONTENT_TYPE_UNKNOWN)); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "1")); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "2")); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "3")); // make sure we don't set content type to "null" assertFalse(extMapHasContentType(unknownTypeContent, extMap, "null")); } @Test public void testPrepareV1ExtensionsKnownAndUnknownContentTypes() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with a kickstart content Product product = TestUtil.createProduct("12345", "a product"); product.setAttribute(Product.Attributes.VERSION, "version"); product.setAttribute(Product.Attributes.VARIANT, "variant"); product.setAttribute(Product.Attributes.TYPE, "SVC"); product.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); product.addContent(content, false); product.addContent(fileContent, false); product.addContent(kickstartContent, false); product.addContent(unknownTypeContent, false); products.add(product); setupEntitlements(ARCH_LABEL, "1.0"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV1Extensions(products, entitlement, "", null); Map<String, X509ExtensionWrapper> map = getEncodedContent(extensions); Map<String, String> extMap = getEncodedContentMap(extensions); // we skip content of unknown type for v1 certs, but other // content should still get added assertTrue(isEncodedContentValid(map)); // other contents are in there assertTrue(map.containsKey(CONTENT_URL)); // unknown is not assertFalse(map.containsKey(CONTENT_TYPE_UNKNOWN)); assertFalse(map.containsKey(CONTENT_URL_UNKNOWN_TYPE)); // we have a yum,file, and kickstart content and // we do not have any unknown content types assertTrue(extMapHasContentType(content, extMap, "1")); assertTrue(extMapHasContentType(fileContent, extMap, "2")); assertTrue(extMapHasContentType(kickstartContent, extMap, "3")); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "1")); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "2")); assertFalse(extMapHasContentType(unknownTypeContent, extMap, "3")); // make sure we don't set content type to "null" assertFalse(extMapHasContentType(unknownTypeContent, extMap, "null")); } private List<org.candlepin.model.dto.Product> getProductModels(Product sku, Set<Product> providedProducts, String prefix, Entitlement e) { List<org.candlepin.model.dto.Product> productModels = v3extensionUtil.createProducts( sku, providedProducts, prefix, new HashMap<String, EnvironmentContent>(), e.getConsumer(), e); return productModels; } @Test public void testPrepareV3EntitlementData() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); products.add(product); consumer.setFact("system.certificate_version", "3.3"); consumer.setFact("uname.machine", "x86_64"); Product product = pool.getProduct(); product.setAttribute(Product.Attributes.WARNING_PERIOD, "20"); product.setAttribute(Product.Attributes.SOCKETS, "4"); product.setAttribute(Product.Attributes.RAM, "8"); product.setAttribute(Product.Attributes.CORES, "4"); product.setAttribute(Product.Attributes.MANAGEMENT_ENABLED, "true"); product.setAttribute(Product.Attributes.STACKING_ID, "45678"); pool.setAttribute(Product.Attributes.VIRT_ONLY, "true"); product.setAttribute(Product.Attributes.SUPPORT_LEVEL, "slevel"); product.setAttribute(Product.Attributes.SUPPORT_TYPE, "stype"); pool.setAccountNumber("account1"); pool.setContractNumber("contract1"); pool.setOrderNumber("order1"); for (ProductContent pc : product.getProductContent()) { pc.setEnabled(false); } Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } assertTrue(map.containsKey("1.3.6.1.4.1.2312.9.6")); assertEquals(map.get("1.3.6.1.4.1.2312.9.6").getValue(), ("3.3")); byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); assertEquals(data.get("consumer"), "test-consumer"); assertEquals(data.get("quantity"), 10); Map<String, Object> subs = (Map<String, Object>) data.get("subscription"); assertEquals(subs.get("sku"), subscription.getProduct().getId()); assertEquals(subs.get("name"), subscription.getProduct().getName()); assertEquals(subs.get("warning"), 20); assertEquals(subs.get("sockets"), 4); assertEquals(subs.get("ram"), 8); assertEquals(subs.get("cores"), 4); assertTrue((Boolean) subs.get("management")); assertEquals(subs.get("stacking_id"), "45678"); assertTrue((Boolean) subs.get("virt_only")); Map<String, Object> service = (Map<String, Object>) subs.get("service"); assertEquals(service.get("level"), "slevel"); assertEquals(service.get("type"), "stype"); Map<String, Object> order = (Map<String, Object>) data.get("order"); assertEquals(order.get("number"), pool.getOrderNumber()); assertTrue(((Integer) order.get("quantity")).intValue() == subscription.getQuantity()); assertNotNull(order.get("start")); assertNotNull(order.get("end")); // assertEquals(order.get("contract"), subscription.getContractNumber()); // assertEquals(order.get("account"), subscription.getAccountNumber()); List<Map<String, Object>> prods = (List<Map<String, Object>>) data.get("products"); List<Map<String, Object>> contents = null; for (Map<String, Object> prod : prods) { assertEquals(prod.get("id"), product.getId()); assertEquals(prod.get("name"), product.getName()); assertEquals(prod.get("version"), product.getAttributeValue(Product.Attributes.VERSION)); String arch = product.hasAttribute(Product.Attributes.ARCHITECTURE) ? product.getAttributeValue(Product.Attributes.ARCHITECTURE) : ""; StringTokenizer st = new StringTokenizer(arch, ","); while (st.hasMoreElements()) { assertTrue(((List) prod.get("architectures")).contains(st.nextElement())); } contents = (List<Map<String, Object>>) prod.get("content"); for (Map<String, Object> cont : contents) { assertEquals(cont.get("id"), CONTENT_ID); assertEquals(cont.get("name"), CONTENT_NAME); assertEquals(cont.get("type"), CONTENT_TYPE); assertEquals(cont.get("label"), CONTENT_LABEL); assertEquals(cont.get("vendor"), CONTENT_VENDOR); assertEquals(cont.get("gpg_url"), CONTENT_GPG_URL); assertEquals(cont.get("path"), "prefix" + CONTENT_URL); assertFalse((Boolean) cont.get("enabled")); assertEquals(cont.get("metadata_expire"), 3200); List<String> arches = new ArrayList<String>(); arches.add(ARCH_LABEL); assertEquals(cont.get("arches"), arches); String rTags = content.getRequiredTags(); st = new StringTokenizer(rTags, ","); while (st.hasMoreElements()) { assertTrue(((List) cont.get("required_tags")) .contains(st.nextElement())); } } } } private void setupEntitlements(String consumerArch, String certVersion) { consumer.setFact("system.certificate_version", certVersion); consumer.setFact("uname.machine", consumerArch); ProductData pdata = subscription.getProduct(); pdata.setAttribute(Product.Attributes.WARNING_PERIOD, "20"); pdata.setAttribute(Product.Attributes.SOCKETS, "4"); pdata.setAttribute(Product.Attributes.RAM, "8"); pdata.setAttribute(Product.Attributes.CORES, "4"); pdata.setAttribute(Product.Attributes.MANAGEMENT_ENABLED, "true"); pdata.setAttribute(Product.Attributes.STACKING_ID, "45678"); entitlement.getPool().setAttribute(Product.Attributes.VIRT_ONLY, "true"); pdata.setAttribute(Product.Attributes.SUPPORT_LEVEL, "slevel"); pdata.setAttribute(Product.Attributes.SUPPORT_TYPE, "stype"); subscription.setAccountNumber("account1"); subscription.setContractNumber("contract1"); subscription.setOrderNumber("order1"); if (pdata.getProductContent() != null) { for (ProductContentData pcd : pdata.getProductContent()) { pcd.setEnabled(false); } } } @Test public void testPrepareV3EntitlementDataNoConsumerArch() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); products.add(product); setupEntitlements(null, "3.3"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); List<Map<String, Object>> prods = (List<Map<String, Object>>) data.get("products"); List<Map<String, Object>> contents = null; for (Map<String, Object> prod : prods) { String arch = product.hasAttribute(Product.Attributes.ARCHITECTURE) ? product.getAttributeValue(Product.Attributes.ARCHITECTURE) : ""; StringTokenizer st = new StringTokenizer(arch, ","); while (st.hasMoreElements()) { assertTrue(((List) prod.get("architectures")).contains(st.nextElement())); } contents = (List<Map<String, Object>>) prod.get("content"); for (Map<String, Object> cont : contents) { assertEquals(cont.get("id"), CONTENT_ID); assertEquals(cont.get("path"), "prefix" + CONTENT_URL); assertFalse((Boolean) cont.get("enabled")); // since we dont know the consumer arch, we dont filter // any contents out List<String> arches = new ArrayList<String>(); arches.add(ARCH_LABEL); assertEquals(cont.get("arches"), arches); } } } @Test public void testPrepareV3EntitlementDataNoContentArch() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // our content with no arch should inherit this arch Product inheritedArchProduct = TestUtil.createProduct("12345", "a product"); inheritedArchProduct.setAttribute(Product.Attributes.VERSION, "version"); inheritedArchProduct.setAttribute(Product.Attributes.VARIANT, "variant"); inheritedArchProduct.setAttribute(Product.Attributes.TYPE, "SVC"); inheritedArchProduct.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); inheritedArchProduct.addContent(noArchContent, false); products.add(inheritedArchProduct); setupEntitlements(ARCH_LABEL, "3.3"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } assertTrue(map.containsKey("1.3.6.1.4.1.2312.9.6")); assertEquals(map.get("1.3.6.1.4.1.2312.9.6").getValue(), ("3.3")); byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); List<Map<String, Object>> prods = (List<Map<String, Object>>) data.get("products"); List<Map<String, Object>> contents = null; for (Map<String, Object> prod : prods) { String arch = product.hasAttribute(Product.Attributes.ARCHITECTURE) ? product.getAttributeValue(Product.Attributes.ARCHITECTURE) : ""; StringTokenizer st = new StringTokenizer(arch, ","); while (st.hasMoreElements()) { assertTrue(((List) prod.get("architectures")).contains(st.nextElement())); } contents = (List<Map<String, Object>>) prod.get("content"); for (Map<String, Object> cont : contents) { // We dont set an arch on Content, but we inherit it // from product, so the arch should match ARCH_LABEL, // that the Product was created with List<String> arches = new ArrayList<String>(); arches.add(ARCH_LABEL); assertEquals(cont.get("arches"), arches); } } } @Test public void testPrepareV3EntitlementDataNoCompatibleArch() throws IOException, GeneralSecurityException { Set<Product> products = new HashSet<Product>(); // product with no compatible content, but marked as 'ALL' arch Product wrongArchProduct = TestUtil.createProduct("12345", "a product"); wrongArchProduct.setAttribute(Product.Attributes.VERSION, "version"); wrongArchProduct.setAttribute(Product.Attributes.VARIANT, "variant"); wrongArchProduct.setAttribute(Product.Attributes.TYPE, "SVC"); wrongArchProduct.setAttribute(Product.Attributes.ARCHITECTURE, "ALL"); // no x86_64, ie ARCH_LABEL String wrongArches = "s390x,s390,ppc64,ia64"; Content wrongArchContent = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, CONTENT_URL, CONTENT_GPG_URL, wrongArches); wrongArchProduct.addContent(wrongArchContent, false); products.clear(); products.add(wrongArchProduct); setupEntitlements(ARCH_LABEL, "3.3"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } assertTrue(map.containsKey("1.3.6.1.4.1.2312.9.6")); assertEquals(map.get("1.3.6.1.4.1.2312.9.6").getValue(), ("3.3")); byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); List<Map<String, Object>> prods = (List<Map<String, Object>>) data.get("products"); List<Map<String, Object>> contents = null; for (Map<String, Object> prod : prods) { String arch = wrongArchProduct.hasAttribute(Product.Attributes.ARCHITECTURE) ? wrongArchProduct.getAttributeValue(Product.Attributes.ARCHITECTURE) : ""; StringTokenizer st = new StringTokenizer(arch, ","); while (st.hasMoreElements()) { assertTrue(((List) prod.get("architectures")).contains(st.nextElement())); } contents = (List<Map<String, Object>>) prod.get("content"); assertTrue(contents.isEmpty()); } } @Test public void testPrepareV3EntitlementDataForDefaults() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(product); consumer.setFact("system.certificate_version", "3.3"); consumer.setFact("uname.machine", "x86_64"); subscription.getProduct().setAttribute(Product.Attributes.WARNING_PERIOD, "0"); subscription.getProduct().setAttribute(Product.Attributes.MANAGEMENT_ENABLED, "false"); entitlement.getPool().setAttribute(Product.Attributes.VIRT_ONLY, "false"); for (ProductContent pc : product.getProductContent()) { pc.setEnabled(true); } Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } assertTrue(map.containsKey("1.3.6.1.4.1.2312.9.6")); assertEquals(map.get("1.3.6.1.4.1.2312.9.6").getValue(), ("3.3")); byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); assertEquals(data.get("consumer"), "test-consumer"); // each has been set to the default and should not be populated in the cert Map<String, Object> subs = (Map<String, Object>) data.get("subscription"); assertNull(subs.get("warning")); assertNull(subs.get("management")); assertNull(subs.get("virt_only")); List<Map<String, Object>> prods = (List<Map<String, Object>>) data.get("products"); for (Map<String, Object> prod : prods) { List<Map<String, Object>> contents = (List<Map<String, Object>>) prod.get("content"); for (Map<String, Object> cont : contents) { assertNull(cont.get("enabled")); } } } @Test public void testPrepareV3EntitlementDataForBooleans() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(product); consumer.setUuid("test-consumer"); consumer.setFact("system.certificate_version", "3.3"); consumer.setFact("uname.machine", "x86_64"); pool.getProduct().setAttribute(Product.Attributes.MANAGEMENT_ENABLED, "1"); entitlement.getPool().setAttribute(Product.Attributes.VIRT_ONLY, "1"); Set<X509ExtensionWrapper> extensions = certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Map<String, X509ExtensionWrapper> map = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : extensions) { map.put(ext.getOid(), ext); } assertTrue(map.containsKey("1.3.6.1.4.1.2312.9.6")); assertEquals(map.get("1.3.6.1.4.1.2312.9.6").getValue(), ("3.3")); byte[] payload = v3extensionUtil.createEntitlementDataPayload(product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); String stringValue = ""; try { stringValue = processPayload(payload); } catch (Exception e) { throw new RuntimeException(e); } Map<String, Object> data = (Map<String, Object>) Util.fromJson(stringValue , Map.class); assertEquals(data.get("consumer"), "test-consumer"); // each has been set to the default and should not be populated in the cert Map<String, Object> subs = (Map<String, Object>) data.get("subscription"); assertTrue((Boolean) subs.get("management")); assertTrue((Boolean) subs.get("virt_only")); } @Test public void testDetachedEntitlementDataNotAddedToCertV1() throws Exception { KeyPair keyPair = new BouncyCastlePKIUtility(null, null, null).generateNewKeyPair(); when(keyPairCurator.getConsumerKeyPair(any(Consumer.class))).thenReturn(keyPair); when(mockedPKI.getPemEncoded(any(X509Certificate.class))).thenReturn("".getBytes()); when(mockedPKI.getPemEncoded(any(Key.class))).thenReturn("".getBytes()); final CertificateSerial serial = mock(CertificateSerial.class); when(serial.getId()).thenReturn(1L); pool.setId("poolId"); doAnswer(new Answer<Map<String, CertificateSerial>>() { @Override public Map<String, CertificateSerial> answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); Map<String, CertificateSerial> map = (Map<String, CertificateSerial>) args[0]; map.put("poolId", serial); return null; } }).when(serialCurator).saveOrUpdateAll(anyMap()); EntitlementCertificate cert = certServiceAdapter.generateEntitlementCert(entitlement, product); assertTrue(!cert.getCert().contains("ENTITLEMENT DATA")); } @Test public void testContentExtension() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(product); product.setProductContent(null); for (Content content : superContent) { product.addContent(content, false); } consumer.setFact("system.certificate_version", "3.3"); consumer.setFact("uname.machine", "x86_64"); Set<X509ByteExtensionWrapper> byteExtensions = certServiceAdapter.prepareV3ByteExtensions( product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); Map<String, X509ByteExtensionWrapper> byteMap = new HashMap<String, X509ByteExtensionWrapper>(); for (X509ByteExtensionWrapper ext : byteExtensions) { byteMap.put(ext.getOid(), ext); } assertTrue(byteMap.containsKey("1.3.6.1.4.1.2312.9.7")); List<String> contentSetList = new ArrayList<String>(); try { contentSetList = v3extensionUtil.hydrateContentPackage( byteMap.get("1.3.6.1.4.1.2312.9.7").getValue()); } catch (Exception e) { throw new RuntimeException(e); } assertEquals(7, contentSetList.size()); for (String url : testUrls) { assertTrue(contentSetList.contains("/prefix" + url)); } } @Test public void testContentExtensionConsumerNoArchFact() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(product); // set of content for an incompatible arch, which should // be in the cert, since this consumer has no arch fact therefore // should match everything String wrongArches = "s390"; String noArchUrl = "/some/place/nice"; Content wrongArchContent = createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, noArchUrl, CONTENT_GPG_URL, wrongArches); product.setProductContent(null); for (Content content : superContent) { product.addContent(content, false); } product.addContent(wrongArchContent, false); consumer.setFact("system.certificate_version", "3.3"); Set<X509ByteExtensionWrapper> byteExtensions = certServiceAdapter.prepareV3ByteExtensions( product, getProductModels(product, products, "prefix", entitlement), entitlement, "prefix", null); Map<String, X509ByteExtensionWrapper> byteMap = new HashMap<String, X509ByteExtensionWrapper>(); for (X509ByteExtensionWrapper ext : byteExtensions) { byteMap.put(ext.getOid(), ext); } assertTrue(byteMap.containsKey("1.3.6.1.4.1.2312.9.7")); List<String> contentSetList = new ArrayList<String>(); try { contentSetList = v3extensionUtil.hydrateContentPackage( byteMap.get("1.3.6.1.4.1.2312.9.7").getValue() ); } catch (Exception e) { throw new RuntimeException(e); } assertEquals(8, contentSetList.size()); for (String url : testUrls) { assertTrue(contentSetList.contains("/prefix" + url)); } // verify our new wrong arch url is in there assertTrue(contentSetList.contains("/prefix" + noArchUrl)); } @Test public void testSpecificLargeContent() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(largeContentProduct); largeContentProduct.setProductContent(null); for (Content content : largeContent) { largeContentProduct.addContent(content, false); } consumer.setFact("system.certificate_version", "3.3"); Set<X509ByteExtensionWrapper> byteExtensions = certServiceAdapter.prepareV3ByteExtensions( product, getProductModels(product, products, "prefix", largeContentEntitlement), largeContentEntitlement, "prefix", null); Map<String, X509ByteExtensionWrapper> byteMap = new HashMap<String, X509ByteExtensionWrapper>(); for (X509ByteExtensionWrapper ext : byteExtensions) { byteMap.put(ext.getOid(), ext); } assertTrue(byteMap.containsKey("1.3.6.1.4.1.2312.9.7")); List<String> contentSetList = new ArrayList<String>(); try { contentSetList = v3extensionUtil.hydrateContentPackage( byteMap.get("1.3.6.1.4.1.2312.9.7").getValue()); } catch (Exception e) { throw new RuntimeException(e); } assertEquals(largeContent.size(), contentSetList.size()); for (String url : largeTestUrls) { assertTrue(contentSetList.contains("/prefix" + url)); } List<String> testList = Arrays.asList(largeTestUrls); for (String url : contentSetList) { assertTrue(testList.contains(url.substring(7))); } } @Test public void testSingleSegmentContent() throws IOException { Set<Product> products = new HashSet<Product>(); products.add(largeContentProduct); largeContentProduct.setProductContent(null); largeContentProduct.addContent(createContent(CONTENT_NAME, CONTENT_ID, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, "/single", CONTENT_GPG_URL, ARCH_LABEL), false); consumer.setFact("system.certificate_version", "3.3"); Set<X509ByteExtensionWrapper> byteExtensions = certServiceAdapter.prepareV3ByteExtensions( product, getProductModels(product, products, "", largeContentEntitlement), largeContentEntitlement, "", null); Map<String, X509ByteExtensionWrapper> byteMap = new HashMap<String, X509ByteExtensionWrapper>(); for (X509ByteExtensionWrapper ext : byteExtensions) { byteMap.put(ext.getOid(), ext); } assertTrue(byteMap.containsKey("1.3.6.1.4.1.2312.9.7")); List<String> contentSetList = new ArrayList<String>(); try { contentSetList = v3extensionUtil.hydrateContentPackage( byteMap.get("1.3.6.1.4.1.2312.9.7").getValue()); } catch (Exception e) { throw new RuntimeException(e); } assertTrue(contentSetList.contains("/single")); } @Test public void testContentExtensionLargeSet() throws IOException { Set<Product> products = new HashSet<Product>(); Product extremeProduct = TestUtil.createProduct("12345", "a product"); extremeProduct.setAttribute(Product.Attributes.VERSION, "version"); extremeProduct.setAttribute(Product.Attributes.VARIANT, "variant"); extremeProduct.setAttribute(Product.Attributes.TYPE, "SVC"); extremeProduct.setAttribute(Product.Attributes.ARCHITECTURE, ARCH_LABEL); products.add(extremeProduct); for (int i = 0; i < 550; i++) { String url = "/content/dist" + i + "/jboss/source" + i; Content content = createContent(CONTENT_NAME + i, CONTENT_ID + i, CONTENT_LABEL, CONTENT_TYPE, CONTENT_VENDOR, url, CONTENT_GPG_URL, ARCH_LABEL); extremeProduct.addContent(content, false); } consumer.setUuid("test-consumer"); consumer.setFact("system.certificate_version", "3.3"); consumer.setFact("uname.machine", "x86_64"); certServiceAdapter.prepareV3Extensions(entitlement, "prefix", null); Set<X509ByteExtensionWrapper> byteExtensions = certServiceAdapter.prepareV3ByteExtensions( extremeProduct, getProductModels(extremeProduct, products, "prefix", entitlement), entitlement, "prefix", null); Map<String, X509ByteExtensionWrapper> byteMap = new HashMap<String, X509ByteExtensionWrapper>(); for (X509ByteExtensionWrapper ext : byteExtensions) { byteMap.put(ext.getOid(), ext); } assertTrue(byteMap.containsKey("1.3.6.1.4.1.2312.9.7")); List<String> contentSetList = new ArrayList<String>(); try { contentSetList = v3extensionUtil.hydrateContentPackage( byteMap.get("1.3.6.1.4.1.2312.9.7").getValue()); } catch (Exception e) { throw new RuntimeException(e); } assertEquals(550, contentSetList.size()); for (int i = 0; i < 550; i++) { String url = "/content/dist" + i + "/jboss/source" + i; assertTrue(contentSetList.contains("/prefix" + url)); } } @Test public void testPathTreeCommonHeadAndTail() { List<org.candlepin.model.dto.Content> contentList = new ArrayList<org.candlepin.model.dto.Content>(); for (int i = 0; i < 20; i++) { org.candlepin.model.dto.Content cont = new org.candlepin.model.dto.Content(); cont.setPath("/head/neck/shoulders/heart" + i + "/waist" + i + "/leg/foot/heel"); contentList.add(cont); } PathNode location = v3extensionUtil.makePathTree(contentList, v3extensionUtil.new PathNode()); v3extensionUtil.printTree(location, 0); assertEquals(location.getChildren().size(), 1); assertEquals(location.getChildren().get(0).getName(), "head"); location = location.getChildren().get(0).getConnection(); assertEquals(location.getChildren().size(), 1); assertEquals(location.getChildren().get(0).getName(), "neck"); location = location.getChildren().get(0).getConnection(); assertEquals(location.getChildren().size(), 1); assertEquals(location.getChildren().get(0).getName(), "shoulders"); location = location.getChildren().get(0).getConnection(); assertEquals(location.getChildren().size(), 20); // find the common footer nodes and make sure they are merged. long legId = -1; long footId = -1; long heelId = -1; for (NodePair np : location.getChildren()) { // np is a "heart" pair assertTrue(np.getName().startsWith("heart")); // now waist node PathNode waist = np.getConnection(); assertEquals(waist.getChildren().size(), 1); assertTrue(waist.getChildren().get(0).getName().startsWith("waist")); // go to "leg" node PathNode leg = waist.getChildren().get(0).getConnection(); if (legId == -1) { legId = leg.getId(); } else { assertEquals(leg.getId(), legId); } assertEquals(leg.getChildren().size(), 1); assertEquals(leg.getChildren().get(0).getName(), "leg"); // go to "foot" node PathNode foot = leg.getChildren().get(0).getConnection(); if (footId == -1) { footId = foot.getId(); } else { assertEquals(foot.getId(), footId); } assertEquals(foot.getChildren().size(), 1); assertEquals(foot.getChildren().get(0).getName(), "foot"); // go to "heel" node PathNode heel = foot.getChildren().get(0).getConnection(); if (heelId == -1) { heelId = heel.getId(); } else { assertEquals(heel.getId(), heelId); } assertEquals(heel.getChildren().size(), 1); assertEquals(heel.getChildren().get(0).getName(), "heel"); } } @Test public void testPathTreeSortsChildNodesAlphabetically() { List<org.candlepin.model.dto.Content> contentList = new ArrayList<org.candlepin.model.dto.Content>(); org.candlepin.model.dto.Content contentA = new org.candlepin.model.dto.Content(); contentA.setPath("/AAA"); org.candlepin.model.dto.Content contentB = new org.candlepin.model.dto.Content(); contentB.setPath("/BBB"); org.candlepin.model.dto.Content contentC = new org.candlepin.model.dto.Content(); contentC.setPath("/CCC"); contentList.add(contentB); contentList.add(contentC); contentList.add(contentA); PathNode location = v3extensionUtil.makePathTree(contentList, v3extensionUtil.new PathNode()); assertEquals(3, location.getChildren().size(), 3); assertEquals("AAA", location.getChildren().get(0).getName()); assertEquals("BBB", location.getChildren().get(1).getName()); assertEquals("CCC", location.getChildren().get(2).getName()); } @Test public void testPathDictionary() throws IOException { List<org.candlepin.model.dto.Content> contentList = new ArrayList<org.candlepin.model.dto.Content>(); org.candlepin.model.dto.Content cont = null; for (int i = 0; i < 20; i++) { cont = new org.candlepin.model.dto.Content(); cont.setPath("/head/neck/shoulders/heart" + i + "/waist" + i + "/leg/foot/heel"); contentList.add(cont); } cont = new org.candlepin.model.dto.Content(); cont.setPath("/head/neck/shoulders/chest/leg"); contentList.add(cont); cont = new org.candlepin.model.dto.Content(); cont.setPath("/head/neck/shoulders/chest/foot"); contentList.add(cont); cont = new org.candlepin.model.dto.Content(); cont.setPath("/head/neck/shoulders/chest/torso/leg"); contentList.add(cont); PathNode location = v3extensionUtil.makePathTree(contentList, v3extensionUtil.new PathNode()); List<String> nodeStrings = v3extensionUtil.orderStrings(location); assertEquals(nodeStrings.size(), 48); // frequency sorted assertEquals(nodeStrings.get(46), "foot"); assertEquals(nodeStrings.get(47), "leg"); } @Test public void testHuffNodeTrieCreationAndTreeSearch() { String[] paths = {"01110", "01111", "0110", "1110", "1111", "010", "100", "101", "110", "00"}; List<HuffNode> huffNodes = new ArrayList<HuffNode>(); List<Object> members = new ArrayList<Object>(); for (int i = 1; i <= 10; i++) { Object o = new Object(); huffNodes.add(v3extensionUtil.new HuffNode(o, i)); members.add(o); } HuffNode trieParent = v3extensionUtil.makeTrie(huffNodes); v3extensionUtil.printTrie(trieParent, 0); assertEquals(trieParent.getWeight(), 55); assertEquals(trieParent.getLeft().getWeight(), 22); assertEquals(trieParent.getRight().getWeight(), 33); int idx = 0; for (Object o : members) { assertEquals(paths[idx], v3extensionUtil.findHuffPath(trieParent, o)); Object found = v3extensionUtil.findHuffNodeValueByBits(trieParent, paths[idx++]); assertEquals(o, found); } } private String processPayload(byte[] payload) throws IOException, UnsupportedEncodingException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InflaterOutputStream ios = new InflaterOutputStream(baos); ios.write(payload); ios.finish(); return baos.toString(); } private Map<String, X509ExtensionWrapper> getEncodedContent( Set<X509ExtensionWrapper> contentExtensions) { Map<String, X509ExtensionWrapper> encodedContent = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : contentExtensions) { encodedContent.put(ext.getValue(), ext); } return encodedContent; } private Map<String, String> getEncodedContentMap( Set<X509ExtensionWrapper> contentExtensions) { Map<String, String> encodedContentMap = new HashMap<String, String>(); for (X509ExtensionWrapper ext : contentExtensions) { encodedContentMap.put(ext.getOid(), ext.getValue()); } return encodedContentMap; } private boolean isEncodedContentValid(Set<X509ExtensionWrapper> contentExtensions) { Map<String, X509ExtensionWrapper> encodedContent = getEncodedContent(contentExtensions); return isEncodedContentValid(encodedContent); } private boolean isEncodedContentValid(Map<String, X509ExtensionWrapper> encodedContent) { return encodedContent.containsKey(CONTENT_LABEL) && // encodedContent.containsKey(CONTENT_ENABLED) && encodedContent.containsKey(CONTENT_GPG_URL) && encodedContent.containsKey(CONTENT_URL) && encodedContent.containsKey(CONTENT_VENDOR) && encodedContent.containsKey(CONTENT_NAME); } class ListContainsContentExtensions extends ArgumentMatcher<Set<X509ExtensionWrapper>> { public boolean matches(Object list) { return isEncodedContentValid((Set) list); } } static class ListContainsEntitlementExtensions extends ArgumentMatcher<Set<X509ExtensionWrapper>> { public boolean matches(Object list) { Map<String, X509ExtensionWrapper> encodedContent = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : (Set<X509ExtensionWrapper>) list) { encodedContent.put(ext.getOid(), ext); } return encodedContent.containsKey("1.3.6.1.4.1.2312.9.4.11") && encodedContent.get("1.3.6.1.4.1.2312.9.4.11") .getValue() .equals(ENTITLEMENT_QUANTITY); } } abstract static class OidMatcher extends ArgumentMatcher<Set<X509ExtensionWrapper>> { protected String value; protected String oid; public OidMatcher(String value, String oid) { this.value = value; this.oid = oid; } public boolean matches(Object list) { Map<String, X509ExtensionWrapper> encodedContent = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : (Set<X509ExtensionWrapper>) list) { encodedContent.put(ext.getOid(), ext); } return encodedContent.containsKey(oid) && encodedContent.get(oid).getValue().equals(value); } } static class ListContainsProvidesManagement extends OidMatcher { public ListContainsProvidesManagement(String value) { super(value, "1.3.6.1.4.1.2312.9.4.14"); } } static class ListContainsSupportLevel extends OidMatcher { public ListContainsSupportLevel(String value) { super(value, "1.3.6.1.4.1.2312.9.4.15"); } } static class ListContainsSupportType extends OidMatcher { public ListContainsSupportType(String value) { super(value, "1.3.6.1.4.1.2312.9.4.16"); } } static class ListContainsStackingId extends OidMatcher { public ListContainsStackingId(String value) { super(value, "1.3.6.1.4.1.2312.9.4.17"); } } static class ListContainsVirtOnlyKey extends OidMatcher { public ListContainsVirtOnlyKey(String value) { super(value, "1.3.6.1.4.1.2312.9.4.18"); } } static class ListContainsOrderNumberKey extends OidMatcher { public ListContainsOrderNumberKey(String value) { super(value, "1.3.6.1.4.1.2312.9.4.2"); } } static class ListContainsContentUrl extends OidMatcher { public ListContainsContentUrl(String value, String contentID) { super(value, "1.3.6.1.4.1.2312.9.2." + contentID + ".1.6"); } } static class ListContainsContentTypeYum extends OidMatcher { public ListContainsContentTypeYum(String value, String contentID) { super(value, "1.3.6.1.4.1.2312.9.2." + contentID + ".1"); } } static class ListContainsContentTypeFile extends OidMatcher { public ListContainsContentTypeFile(String value, String contentID) { super(value, "1.3.6.1.4.1.2312.9.2." + contentID + ".2"); } } static class ListContainsContentTypeKickstart extends OidMatcher { public ListContainsContentTypeKickstart(String value, String contentID) { super(value, "1.3.6.1.4.1.2312.9.2." + contentID + ".3"); } } abstract static class OidAbsentMatcher extends ArgumentMatcher<Set<X509ExtensionWrapper>> { protected String oid; public OidAbsentMatcher(String oid) { this.oid = oid; } public boolean matches(Object list) { Map<String, X509ExtensionWrapper> encodedContent = new HashMap<String, X509ExtensionWrapper>(); for (X509ExtensionWrapper ext : (Set<X509ExtensionWrapper>) list) { encodedContent.put(ext.getOid(), ext); } return !encodedContent.containsKey(oid); } } static class ListDoesNotContainSupportLevel extends OidAbsentMatcher { public ListDoesNotContainSupportLevel() { super("1.3.6.1.4.1.2312.9.4.15"); } } static class ListDoesNotContainSupportType extends OidAbsentMatcher { public ListDoesNotContainSupportType() { super("1.3.6.1.4.1.2312.9.4.16"); } } private String[] largeTestUrls = { "/content/beta/rhel/server/6/$releasever/$basearch/sap/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/sap/os", "/content/dist/rhel/server/6/$releasever/$basearch/sap/debug", "/content/dist/rhel/server/5/$releasever/$basearch/sap/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/sap/source/SRPMS", "/content/dist/rhel/server/5/$releasever/$basearch/sap/os", "/content/beta/rhel/server/5/$releasever/$basearch/sap/debug", "/content/beta/rhel/server/5/$releasever/$basearch/sap/os", "/content/beta/rhel/server/5/$releasever/$basearch/sap/source/SRPMS", "/content/beta/rhel/server/6/$releasever/$basearch/sap/os", "/content/beta/rhel/server/6/$releasever/$basearch/sap/debug", "/content/dist/rhel/server/5/$releasever/$basearch/sap/debug", "/content/beta/rhel/server/5/$releasever/$basearch/source/iso", "/content/dist/rhel/server/5/$releasever/$basearch/os", "/content/beta/rhel/server/6/$releasever/$basearch/optional/debug", "/content/beta/rhel/server/6/$releasever/$basearch/cf-tools/1.0/os", "/content/beta/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/os", "/content/beta/rhel/server/5/$releasever/$basearch/vt/debug", "/content/beta/rhel/server/6/$releasever/$basearch/cf-tools/1.0/debug", "/content/beta/rhel/server/6/$releasever/$basearch/optional/source/SRPMS", "/content/dist/rhel/server/5/$releasever/$basearch/debug", "/content/dist/rhel/server/6/$releasever/$basearch/supplementary/debug", "/content/dist/rhel/server/5/$releasever/$basearch/supplementary/os", "/content/dist/rhel/server/6/$releasever/$basearch/os", "/content/dist/rhel/server/6/$releasever/$basearch/optional/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/source/iso", "/content/dist/rhel/server/5/$releasever/$basearch/productivity/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/cf-tools/1.0/debug", "/content/dist/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/os", "/content/dist/rhel/server/6/$releasever/$basearch/supplementary/os", "/content/dist/rhel/server/5/$releasever/$basearch/vt/os", "/content/dist/rhel/server/6/$releasever/$basearch/optional/os", "/content/beta/rhel/server/5/$releasever/$basearch/supplementary/debug", "/content/dist/rhel/server/6/$releasever/$basearch/supplementary/iso", "/content/beta/rhel/server/5/$releasever/$basearch/debug", "/content/beta/rhel/server/6/$releasever/$basearch/subscription-asset-manager/" + "debug", "/content/dist/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/source/SRPMS", "/content/beta/rhel/server/6/$releasever/$basearch/subscription-asset-manager/" + "source/SRPMS", "/content/beta/rhel/server/6/$releasever/$basearch/os", "/content/dist/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/supplementary/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/supplementary/os", "/content/dist/rhel/server/5/$releasever/$basearch/source/iso", "/content/beta/rhel/server/5/$releasever/$basearch/vt/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/subscription-asset-manager/1/" + "debug", "/content/beta/rhel/server/5/$releasever/$basearch/supplementary/iso", "/content/dist/rhel/server/5/$releasever/$basearch/productivity/debug", "/content/beta/rhel/server/6/$releasever/$basearch/cf-tools/1.0/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/cf-tools/1.0/os", "/content/beta/rhel/server/6/$releasever/$basearch/source/iso", "/content/dist/rhel/server/6/$releasever/$basearch/cf-tools/1.0/source/SRPMS", "/content/dist/rhel/server/5/$releasever/$basearch/iso", "/content/dist/rhel/server/5/$releasever/$basearch/productivity/os", "/content/beta/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/debug", "/content/beta/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/debug", "/content/dist/rhel/server/5/$releasever/$basearch/vt/debug", "/content/beta/rhel/server/6/$releasever/$basearch/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/cf-tools/1.0/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/os", "/content/dist/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/debug", "/content/beta/rhel/server/6/$releasever/$basearch/supplementary/debug", "/content/dist/rhel/server/5/$releasever/$basearch/cf-tools/1.0/os", "/content/beta/rhel/server/6/$releasever/$basearch/iso", "/content/beta/rhel/server/5/$releasever/$basearch/iso", "/content/beta/rhel/server/6/$releasever/$basearch/supplementary/os", "/content/dist/rhel/server/5/$releasever/$basearch/supplementary/iso", "/content/beta/rhel/server/5/$releasever/$basearch/cf-tools/1.0/os", "/content/beta/rhel/server/6/$releasever/$basearch/optional/os", "/content/beta/rhel/server/6/$releasever/$basearch/supplementary/iso", "/content/dist/rhel/server/5/$releasever/$basearch/source/SRPMS", "/content/beta/rhel/server/6/$releasever/$basearch/debug", "/content/beta/rhel/server/6/$releasever/$basearch/subscription-asset-manager/os", "/content/dist/rhel/server/5/$releasever/$basearch/supplementary/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/iso", "/content/dist/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/debug", "/content/dist/rhel/server/6/$releasever/$basearch/subscription-asset-manager/1/os", "/content/dist/rhel/server/6/$releasever/$basearch/debug", "/content/beta/rhel/server/6/$releasever/$basearch/supplementary/source/SRPMS", "/content/dist/rhel/server/5/$releasever/$basearch/vt/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/os", "/content/beta/rhel/server/5/$releasever/$basearch/rhev-agent/3.0/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/subscription-asset-manager/1/" + "source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/os", "/content/dist/rhel/server/6/$releasever/$basearch/supplementary/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/vt/os", "/content/dist/rhel/server/5/$releasever/$basearch/supplementary/debug", "/content/dist/rhel/server/6/$releasever/$basearch/optional/debug", "/content/dist/rhel/server/5/$releasever/$basearch/cf-tools/1.0/source/SRPMS", "/content/beta/rhel/server/6/$releasever/$basearch/rhev-agent/3.0/source/SRPMS", "/content/beta/rhel/server/5/$releasever/$basearch/source/SRPMS", "/content/dist/rhel/server/6/$releasever/$basearch/source/SRPMS", "/content/rhb/rhel/client/6/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/workstation/5/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/client/5/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/client/5/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/client/5/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/computenode/6/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/server/6/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/workstation/6/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/server/6/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/workstation/5/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/computenode/6/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/workstation/6/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/workstation/6/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/computenode/6/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/client/6/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/server/6/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/workstation/5/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/client/6/$releasever/$basearch/devtoolset/source/SRPMS", "/content/rhb/rhel/server/5/$releasever/$basearch/devtoolset/debug", "/content/rhb/rhel/server/5/$releasever/$basearch/devtoolset/os", "/content/rhb/rhel/server/5/$releasever/$basearch/devtoolset/source/SRPMS"}; }