<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Hutchison</title>
    <description>The latest articles on DEV Community by David Hutchison (@davidhutchison).</description>
    <link>https://dev.to/davidhutchison</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F32152%2F387ee500-f9e0-427a-b66b-7486ca24b785.png</url>
      <title>DEV Community: David Hutchison</title>
      <link>https://dev.to/davidhutchison</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidhutchison"/>
    <language>en</language>
    <item>
      <title>Publishing a Compodoc Site to Nexus</title>
      <dc:creator>David Hutchison</dc:creator>
      <pubDate>Wed, 27 May 2020 22:24:00 +0000</pubDate>
      <link>https://dev.to/davidhutchison/publishing-a-compodoc-site-to-nexus-1hei</link>
      <guid>https://dev.to/davidhutchison/publishing-a-compodoc-site-to-nexus-1hei</guid>
      <description>&lt;p&gt;Recently I have been looking at &lt;a href="https://compodoc.app"&gt;Compodoc&lt;/a&gt; for generating documentation sites for Angular projects. Some of these projects are for libraries that will be reused elsewhere, so this documentation requires to be published somewhere.&lt;/p&gt;

&lt;p&gt;The libraries are published as NPM modules to a &lt;a href="https://www.sonatype.com/nexus-repository-oss"&gt;Sonatype Nexus&lt;/a&gt; instance, so it would be ideal if the documentation could be published to the same place.&lt;/p&gt;

&lt;p&gt;Nexus has a &lt;a href="https://help.sonatype.com/repomanager3/formats/raw-repositories"&gt;Raw Repository&lt;/a&gt; type which can be used for hosting static websites. The linked page includes details of how to configure a repository, how to publish to it from Maven, and using &lt;code&gt;curl&lt;/code&gt; to upload single files using HTTP requests.&lt;/p&gt;

&lt;p&gt;Based on this &lt;code&gt;curl&lt;/code&gt; approach I have put together a bash script below that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;has a number of configuration options for the user, nexus server, repository name, and documentation directory to upload&lt;/li&gt;
&lt;li&gt;prompts for the password for the user to use&lt;/li&gt;
&lt;li&gt;uses the git repository name as a subdirectory to store items in within the nexus repository, so that the same nexus repository could be used as a central location for generated documentation for multiple projects&lt;/li&gt;
&lt;li&gt;iterates through every file in the configured documentation directory and uploads it to nexus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once this script runs, you will be able to see the contents of the site in the browse view for the repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PSnNhwbL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/compodoc_publish/browse_view.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PSnNhwbL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/compodoc_publish/browse_view.png" alt="Repository browse view" title="Repository browse view showing generated site files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on the &lt;code&gt;index.html&lt;/code&gt; file will show the details, including the direct path to the artefact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--figasHfB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/compodoc_publish/index_details.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--figasHfB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/compodoc_publish/index_details.png" alt="Index details" title="Details of the index.html file including the resource path"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will be the URL that your documentation site will be available at. The script below assumes there will be an &lt;code&gt;index.html&lt;/code&gt; file and outputs the direct URL to this resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Configure username to use. The password will be prompted for later.
USER=admin

# The URL for the Nexus server
NEXUS_SERVER=https://nexus.example.com
# The name of the raw repository
REPOSITORY_NAME=documentation
# Each project will have its own directory based on the git repository name
GIT_REPO_NAME=$(basename -s .git $(git config --get remote.origin.url))

# Make our base Nexus repository directory URL
DEST_REPO_DIRECTORY="${NEXUS_SERVER}/repository/${REPOSITORY_NAME}/${GIT_REPO_NAME}"

# The directory to get the contents of to upload
LOCAL_DOCS=./documentation

# Prompt for the user password to use
read -s -p "Password for $USER: " PASS

# Find all the files in the directory and upload them. 
# This may have issues if you had spaces in filenames, but 
# generated documentation produced by compodoc doesn't

for file in $(find "$LOCAL_DOCS" -type f -print); do

    # Need to trim the local documentation directory part off the string
    destination_file="${file/$LOCAL_DOCS/}"

    # Upload the file
    # This uses verbose logging, you will want to reduce the logging here
    # if using this in a production environment
    curl -v --user "${USER}:${PASS}" --upload-file "$file" "${DEST_REPO_DIRECTORY}${destination_file}"

done

echo "If no errors were reported above, your documentation site will be available at ${DEST_REPO_DIRECTORY}/index.html"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>compodoc</category>
      <category>nexus</category>
    </item>
    <item>
      <title>Restricting Software Libraries in Nexus</title>
      <dc:creator>David Hutchison</dc:creator>
      <pubDate>Thu, 12 Mar 2020 20:29:00 +0000</pubDate>
      <link>https://dev.to/davidhutchison/restricting-software-libraries-in-nexus-311i</link>
      <guid>https://dev.to/davidhutchison/restricting-software-libraries-in-nexus-311i</guid>
      <description>&lt;p&gt;As part of looking in to controlling the third party libraries which could be included for use by a project, I wondered if it was possible to effectively apply an approved whitelist at the &lt;a href="https://www.sonatype.com/nexus-repository-oss"&gt;Sonatype Nexus&lt;/a&gt; level. This would only be effective if developers and CI tools are restricted in their web access and cannot contact the central artefact repositories directly, and so are forced to use Nexus as a mirror.&lt;/p&gt;

&lt;p&gt;It turns out that this is possible, and the Nexus documentation is pretty good if you know the pieces of the puzzle that need to be joined together to make this work. &lt;a href="https://help.sonatype.com/repomanager3/security/roles"&gt;Roles&lt;/a&gt;, which can be assigned to specific &lt;a href="https://help.sonatype.com/repomanager3/security/users"&gt;users&lt;/a&gt; or an anonymous user, are made up of privileges. &lt;a href="https://help.sonatype.com/repomanager3/configuration/repository-management#RepositoryManagement-ManagingSelectorPermissions"&gt;Privileges&lt;/a&gt; can include &lt;a href="https://help.sonatype.com/repomanager3/configuration/repository-management#RepositoryManagement-ContentSelectors"&gt;Content Selectors&lt;/a&gt; to restrict the results which are returned. When combining these things, we can effectively build a whitelist. As this approach is role based, different rules can be used depending on who the caller is.&lt;/p&gt;

&lt;p&gt;While the examples in this post are for applying this to Maven dependencies, the same concept can be used with other repository types supported by Nexus such as NPM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Selectors
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://help.sonatype.com/repomanager3/configuration/repository-management#RepositoryManagement-ContentSelectors"&gt;Content selectors&lt;/a&gt; provide a means for you to select specific content from all of your content. The content you select is evaluated against expressions written in CSEL (Content Selector Expression Language).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, to configure a selector for only Apache Software Foundation libraries, we would use these settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J2-r8rR6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/content_selector_asf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J2-r8rR6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/content_selector_asf.png" alt="ASF Content Selector" title="Configuration settings for an Apache Software Foundation Content Selector"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a variety of options which can be used for making the filter conditions, based on the repository type and the type of artifact.&lt;/p&gt;

&lt;p&gt;Path based searches can be used for all repository formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;format == "maven2" and path =^ "/org/apache/"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Maven format repositories can use additional filters based on the Maven coordinates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;format == "maven2" and coordinate.groupId == "org.apache"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The options which are available as properties of “coordinate” are not well documented, but are included in the code as the values for the “VALID_REFERENCES” constant in &lt;a href="https://github.com/sonatype/nexus-public/blob/master/components/nexus-selector/src/main/java/org/sonatype/nexus/selector/CselValidator.java"&gt;CselValidator.java&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privileges
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://help.sonatype.com/repomanager3/configuration/repository-management#RepositoryManagement-ManagingSelectorPermissions"&gt;Repository Content Selector Privilege&lt;/a&gt; is created using this Content Selector. This means that for each Content Selector that is to be added to our whitelist we require a Privilege.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VJ0KGiya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/privilege_asf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VJ0KGiya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/privilege_asf.png" alt="ASF Content Selector Privilege" title="Configuration settings for an Apache Software Foundation Privilege"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Roles
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://help.sonatype.com/repomanager3/security/roles"&gt;role&lt;/a&gt; is configured to group privileges together to form a group or permissions which a user can be assigned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7daHf1BF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/role_restricted_anon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7daHf1BF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/role_restricted_anon.png" alt="Role linked to our custom privileges" title="Configuration settings for our custom role"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Users
&lt;/h2&gt;

&lt;p&gt;One or many roles can then be assigned to a &lt;a href="https://help.sonatype.com/repomanager3/security/users"&gt;user&lt;/a&gt;, including to the anonymous user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5yvs7G26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/user_anon_roles.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5yvs7G26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.devwithimagination.com/images/nexus_whitelist/user_anon_roles.png" alt="Anonymous user linked to our custom role" title="Configuration settings for the anonymous user with our custom role"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Implementation
&lt;/h2&gt;

&lt;p&gt;For simplicity of a test, this was tested using cURL to verify that a whitelisted Maven artefact could be downloaded, while an item not in the list could not.&lt;/p&gt;

&lt;p&gt;An approved item returns an HTTP 200 (OK) response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MacBook:payara dhutchison$ curl -I https://nexus.lan/repository/maven-central/org/apache/ant/ant/1.10.5/ant-1.10.5.pom
HTTP/2 200 
content-security-policy: sandbox allow-forms allow-modals allow-popups allow-presentation allow-scripts allow-top-navigation
content-type: application/xml
date: Tue, 25 Feb 2020 22:10:49 GMT
etag: "1d48137927c0900a9d8e85e640b6cb74"
last-modified: Tue, 10 Jul 2018 04:54:03 GMT
server: Nexus/3.20.1-01 (OSS)
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
content-length: 10470

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Trying the same test for an item not in our approved whitelist will fail with an HTTP 401 (Unauthorized) response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MacBook:payara dhutchison$ curl -I https://nexus.lan/repository/maven-central/xalan/xalan/2.7.2/xalan-2.7.2.pom
HTTP/2 401 
content-security-policy: sandbox allow-forms allow-modals allow-popups allow-presentation allow-scripts allow-top-navigation
date: Tue, 25 Feb 2020 22:13:08 GMT
server: Nexus/3.20.1-01 (OSS)
www-authenticate: BASIC realm="Sonatype Nexus Repository Manager"
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
content-length: 0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>nexus</category>
      <category>maven</category>
      <category>sdlc</category>
    </item>
  </channel>
</rss>
