This commit is contained in:
Rui Lopes 2016-11-27 13:32:59 +00:00
commit aae25fc85e
15 changed files with 843 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vagrant/
.idea/
provision/provision-nexus/sources/

32
README.md Normal file
View File

@ -0,0 +1,32 @@
This is a Vagrant Environment for a [Nexus Repository OSS](https://github.com/sonatype/nexus-public) service.
This will:
* Configure Nexus through Groovy scripts.
* Create the `adhoc-package` repository.
* Configure the NuGet `nuget-hosted` repository to accept pushing with an API key.
* Schedule a task to remove the old snapshots from the `maven-snapshots` repository.
* Create users and a custom `deployer` role.
* For more details look inside the [provision/provision-nexus](provision/provision-nexus) directory.
* Setup nginx as a Nexus HTTPS proxy and static file server.
* Test the installed repositories by [using and publishing to them](provision/test.sh).
**NB** If you are new to Groovy, be sure to check the [Groovy Learn X in Y minutes page](https://learnxinyminutes.com/docs/groovy/).
# Usage
Build and install the [Ubuntu Base Box](https://github.com/rgl/ubuntu-vagrant).
Add the following entry to your `/etc/hosts` file:
```
192.168.56.3 nexus.example.com
```
Run `vagrant up` to launch the environment. See its output to known how to login at the
[local Nexus home page](https://nexus.example.com) as `admin` (you can also login with
one of the example accounts, e.g. `alice.doe` and password `password`).
**NB** nginx is setup with a self-signed certificate that you have to trust before being
able to access the local Nexus home page.

13
Vagrantfile vendored Normal file
View File

@ -0,0 +1,13 @@
Vagrant.configure(2) do |config|
config.vm.box = 'ubuntu-16.04-amd64'
config.vm.hostname = 'nexus.example.com'
config.vm.network 'private_network', ip: '192.168.56.3'
config.vm.provider 'virtualbox' do |vb|
vb.linked_clone = true
vb.cpus = 2
vb.memory = 4096
end
config.vm.provision :shell, path: 'provision/provision.sh'
config.vm.provision :shell, path: 'provision/test.sh'
config.vm.provision :shell, path: 'provision/summary.sh'
end

View File

@ -0,0 +1,11 @@
#!/bin/bash
set -eux
. /vagrant/provision/nexus-groovy.sh
# list existing scripts.
#http -a "$admin_username:$admin_password" http://localhost:8081/service/siesta/rest/v1/script | jq .
# run the provision script.
response=$(nexus-groovy provision)
echo "$response" | jq '.result | fromjson'

31
provision/nexus-groovy.sh Normal file
View File

@ -0,0 +1,31 @@
#!/bin/bash
set -eux
admin_username=${admin_username:-admin}
admin_password=${admin_password:-admin123}
# see https://books.sonatype.com/nexus-book/3.0/reference/scripting.html
function nexus-groovy {
local source_filename="/vagrant/provision/provision-nexus/src/main/groovy/$1.groovy"
local delete_result=$(http \
-a "$admin_username:$admin_password" \
--ignore-stdin \
DELETE http://localhost:8081/service/siesta/rest/v1/script/provision.groovy)
local create_result=$(http \
-a "$admin_username:$admin_password" \
--ignore-stdin \
--check-status \
POST http://localhost:8081/service/siesta/rest/v1/script \
name=provision.groovy \
type=groovy \
"content=@$source_filename")
http \
-a "$admin_username:$admin_password" \
--ignore-stdin \
--check-status \
POST http://localhost:8081/service/siesta/rest/v1/script/provision.groovy/run \
Content-Type:text/plain
}

View File

@ -0,0 +1,17 @@
sources: sources-download
mkdir -p sources
cd sources && \
find ~/.m2/repository/org/sonatype/nexus \
-name '*-sources.jar' \
-exec bash -c 'mkdir -p "$$(basename {})"' \; \
-exec bash -c '7z -y "-o$$(basename {})" x {}' \;
#find sources -type f -name '*.groovy'
#grep -r 'NuGet API-Key Realm' sources
sources-download:
mvn dependency:sources
clean:
rm -rf sources
.PHONY: sources sources-download clean

View File

@ -0,0 +1,35 @@
Open this directory with [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/#section=windows).
Inside IDEA you can browse the sources with `control+left-click` to see which methods are available.
To execute the `src/main/groovy/provision.groovy` file inside the Vagrant
environment run `bash /vagrant/execute-provision.groovy-script.sh`.
For more information see the Nexus [scripting documentation](https://books.sonatype.com/nexus-book/3.0/reference/scripting.html) and [examples](https://github.com/sonatype/nexus-book-examples/tree/nexus-3.0.x/scripting).
# Source Code
Run `make sources` to download and extract all the source code into the `sources` directory.
You are now able to `find` and `grep` it.
For example, list all `.groovy` files:
```sh
find sources -type f -name '*groovy'
```
Get all exposed API objects:
```sh
grep -ri ApiImpl sources
```
Where you can see the definition of the global variables that are available on a groovy script:
```
sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'security', type: 'org.sonatype.nexus.security.internal.SecurityApiImpl'
sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'core', type: 'org.sonatype.nexus.internal.provisioning.CoreApiImpl'
sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'repository', type: 'org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl'
sources/org.sonatype.nexus.script/nexus-script.gdsl: property name: 'blobStore', type: 'org.sonatype.nexus.internal.provisioning.BlobStoreApiImpl'
```

View File

@ -0,0 +1,45 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.automation</groupId>
<artifactId>provision-nexus</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<nx-version>3.1.0-04</nx-version>
</properties>
<dependencies>
<dependency>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-core</artifactId>
<version>${nx-version}</version>
</dependency>
<dependency>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-script</artifactId>
<version>${nx-version}</version>
</dependency>
<dependency>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-security</artifactId>
<version>${nx-version}</version>
</dependency>
<dependency>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-repository</artifactId>
<version>${nx-version}</version>
</dependency>
<dependency>
<groupId>org.sonatype.nexus.plugins</groupId>
<artifactId>nexus-repository-maven</artifactId>
<version>${nx-version}</version>
</dependency>
<dependency>
<groupId>org.sonatype.nexus.plugins</groupId>
<artifactId>nexus-script-plugin</artifactId>
<version>${nx-version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-core:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-bootstrap:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.16" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.16" level="project" />
<orderEntry type="library" name="Maven: uk.org.lidalia:sysout-over-slf4j:1.0.2" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.plexus:plexus-interpolation:1.22" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-supportzip-api:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.7.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-email:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.4" level="project" />
<orderEntry type="library" name="Maven: com.sun.mail:javax.mail:1.5.2" level="project" />
<orderEntry type="library" name="Maven: javax.activation:activation:1.1.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-ssl:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.geronimo.framework:geronimo-crypto:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-webhooks:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-script:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-common:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.0" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:18.0" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:google-guava-eventbus:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.sisu:org.eclipse.sisu.inject:0.3.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.servicemix.bundles:org.apache.servicemix.bundles.javax-inject:1_2" level="project" />
<orderEntry type="library" name="Maven: org.apache.servicemix.bundles:org.apache.servicemix.bundles.aopalliance:1.0_6" level="project" />
<orderEntry type="library" name="Maven: com.google.inject:guice:4.0" level="project" />
<orderEntry type="library" name="Maven: com.google.inject.extensions:guice-assistedinject:4.0" level="project" />
<orderEntry type="library" name="Maven: javax.enterprise:cdi-api:1.2" level="project" />
<orderEntry type="library" name="Maven: javax.el:javax.el-api:3.0.0" level="project" />
<orderEntry type="library" name="Maven: javax.interceptor:javax.interceptor-api:1.2" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.2" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.goodies:goodies-common:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.gossip:gossip-support:1.8" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.gossip:gossip-bootstrap:1.8" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.goodies:goodies-lifecycle:2.2.1" level="project" />
<orderEntry type="library" name="Maven: joda-time:joda-time:2.8.2" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.groovy:groovy-all:2.4.4" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-validation:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
<orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.1.2.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.1.3.GA" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.0.0" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.web:javax.el:2.2.6" level="project" />
<orderEntry type="library" name="Maven: com.thoughtworks.paranamer:paranamer:2.8" level="project" />
<orderEntry type="library" name="Maven: javax.ws.rs:javax.ws.rs-api:2.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.ivy:ivy:2.3.0" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-security:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-audit:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-formfields:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.goodies:goodies-i18n:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-jmx:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-cache:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.geronimo.specs:geronimo-jcache_1.0_spec:1.0-alpha-1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus.bundles:org.sonatype.nexus.bundles.ehcache:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.ehcache:jcache:1.0.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-crypto:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.52" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcpg-jdk15on:1.52" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.52" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.16" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.2" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: com.google.inject.extensions:guice-servlet:4.0" level="project" />
<orderEntry type="library" name="Maven: com.google.inject.extensions:guice-multibindings:4.0" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-repository:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-capability:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-mime:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.tika:tika-core:1.11" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.7.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.7.0" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-orient:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: com.orientechnologies:orientdb-core:2.2.11" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.1" level="project" />
<orderEntry type="library" name="Maven: com.orientechnologies:orientdb-server:2.2.11" level="project" />
<orderEntry type="library" name="Maven: com.orientechnologies:orientdb-client:2.2.11" level="project" />
<orderEntry type="library" name="Maven: com.orientechnologies:orientdb-tools:2.2.11" level="project" />
<orderEntry type="library" name="Maven: javax.mail:mail:1.4.7" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-blobstore-api:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-blobstore-file:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-thread:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: com.squareup:tape:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-httpclient:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.1" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.4" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-elasticsearch:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.servicemix.bundles:org.apache.servicemix.bundles.elasticsearch:2.2.0_1" level="project" />
<orderEntry type="library" name="Maven: com.spatial4j:spatial4j:0.5" level="project" />
<orderEntry type="library" name="Maven: org.joda:joda-convert:1.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.6.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.6.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.6.2" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty:3.10.5.Final" level="project" />
<orderEntry type="library" name="Maven: com.ning:compress-lzf:1.0.2" level="project" />
<orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.6" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.3.1" level="project" />
<orderEntry type="library" name="Maven: com.vividsolutions:jts:1.13" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-transaction:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-scheduling:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-selector:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-jexl3:3.0" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus:nexus-commands:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.osgi:org.osgi.core:6.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.karaf.shell:org.apache.karaf.shell.core:4.0.5" level="project" />
<orderEntry type="library" name="Maven: jline:jline:2.14.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.karaf.jaas:org.apache.karaf.jaas.boot:4.0.5" level="project" />
<orderEntry type="library" name="Maven: org.apache.sshd:sshd-core:0.14.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.karaf.shell:org.apache.karaf.shell.commands:4.0.5" level="project" />
<orderEntry type="library" name="Maven: org.jledit:core:0.2.1" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus.plugins:nexus-repository-maven:3.1.0-04" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-model:3.3.3" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.plexus:plexus-utils:3.0.20" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-repository-metadata:3.3.3" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.aether:aether-api:1.0.2.v20150114" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.aether:aether-util:1.0.2.v20150114" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.aether:aether-spi:1.0.2.v20150114" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.indexer:indexer-reader:5.1.2-816025a" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.archetype:archetype-catalog:2.4" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.nexus.plugins:nexus-script-plugin:3.1.0-04" level="project" />
</component>
</module>

View File

@ -0,0 +1,12 @@
import org.sonatype.nexus.security.user.UserSearchCriteria
// delete all users except the allowed ones.
allowedUsers = [
"anonymous",
"admin",
"jenkins",
]
security.securitySystem
.searchUsers(new UserSearchCriteria())
.findAll { !allowedUsers.contains(it.userId) }
.forEach { security.securitySystem.deleteUser(it.userId) }

View File

@ -0,0 +1,16 @@
import groovy.json.JsonOutput
import org.sonatype.nexus.security.authc.apikey.ApiKeyStore
import org.apache.shiro.subject.SimplePrincipalCollection
def getNuGetApiKey(String userName) {
realmName = "NexusAuthenticatingRealm"
apiKeyDomain = "NuGetApiKey"
principal = new SimplePrincipalCollection(userName, realmName)
keyStore = container.lookup(ApiKeyStore.class.getName())
apiKey = keyStore.getApiKey(apiKeyDomain, principal)
return apiKey.toString()
}
return JsonOutput.toJson([
apiKey: getNuGetApiKey("jenkins"),
])

View File

@ -0,0 +1,117 @@
// run this file inside the Vagrant environment with bash /vagrant/execute-provision.groovy-script.sh
// see https://books.sonatype.com/nexus-book/3.0/reference/scripting.html
// see https://github.com/sonatype/nexus-book-examples/tree/nexus-3.0.x/scripting/nexus-script-example
import groovy.json.JsonOutput
import org.sonatype.nexus.security.user.UserSearchCriteria
import org.sonatype.nexus.security.authc.apikey.ApiKeyStore
import org.sonatype.nexus.security.realm.RealmManager
import org.apache.shiro.subject.SimplePrincipalCollection
import org.sonatype.nexus.scheduling.TaskScheduler
import org.sonatype.nexus.scheduling.schedule.Daily
// create a raw repository backed by the default blob store.
// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.0.x/scripting/complex-script/rawRepositories.groovy
// see https://books.sonatype.com/nexus-book/3.0/reference/raw.html#_uploading_files_to_hosted_raw_repositories
repository.createRawHosted("adhoc-package", "default")
// see http://stackoverflow.com/questions/8138164/groovy-generate-random-string-from-given-character-set
def random(String alphabet, int n) {
new Random().with {
(1..n).collect { alphabet[nextInt(alphabet.length())] }.join()
}
}
jenkinsPassword = random((('A'..'Z')+('a'..'z')+('0'..'9')).join(), 16)
// set the base url. this is used when sending emails.
// see https://books.sonatype.com/nexus-book/3.0/reference/admin.html#admin-base-url
core.baseUrl("https://" + java.net.InetAddress.getLocalHost().getCanonicalHostName())
// schedule a task to remove old snapshots from the maven-snapshots repository.
// see https://github.com/sonatype/nexus-public/blob/555cc59e7fa659c0a1a4fbc881bf3fcef0e9a5b6/components/nexus-scheduling/src/main/java/org/sonatype/nexus/scheduling/TaskScheduler.java
// see https://github.com/sonatype/nexus-public/blob/555cc59e7fa659c0a1a4fbc881bf3fcef0e9a5b6/plugins/nexus-coreui-plugin/src/main/java/org/sonatype/nexus/coreui/TaskComponent.groovy
taskScheduler = (TaskScheduler)container.lookup(TaskScheduler.class.getName())
taskConfiguration = taskScheduler.createTaskConfigurationInstance("repository.maven.remove-snapshots")
taskConfiguration.name = "remove old snapshots from the maven-snapshots repository"
// NB to see the available properties uncomment the tasksDescriptors property from JsonOutput.toJson at the end of this script.
taskConfiguration.setString("repositoryName", "maven-snapshots")
taskConfiguration.setString("minimumRetained", "1")
taskConfiguration.setString("snapshotRetentionDays", "30")
// TODO taskConfiguration.setAlertEmail("TODO")
taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next()))
// enable the NuGet API-Key Realm.
realmManager = container.lookup(RealmManager.class.getName())
realmManager.enableRealm("NuGetApiKey")
// the intent is to get or create an NuGet API Key like the one we can see on the user page:
// http://nexus.example.com:8081/#user/nugetapitoken.
def getOrCreateNuGetApiKey(String userName) {
realmName = "NexusAuthenticatingRealm"
apiKeyDomain = "NuGetApiKey"
principal = new SimplePrincipalCollection(userName, realmName)
keyStore = container.lookup(ApiKeyStore.class.getName())
apiKey = keyStore.getApiKey(apiKeyDomain, principal)
if (apiKey == null) {
apiKey = keyStore.createApiKey(apiKeyDomain, principal)
}
return apiKey.toString()
}
// create users in the deployer role.
// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.0.x/scripting/complex-script/security.groovy#L38
def addDeployerUser(firstName, lastName, email, userName, password) {
if (!security.securitySystem.listRoles().any { it.getRoleId() == "deployer" }) {
privileges = [
"nx-search-read",
"nx-repository-view-*-*-read",
"nx-repository-view-*-*-browse",
"nx-repository-view-*-*-add",
"nx-repository-view-*-*-edit",
"nx-apikey-all"]
security.addRole("deployer", "deployer", "deployment on all repositories", privileges, [])
}
try {
user = security.securitySystem.getUser(userName);
} catch (org.sonatype.nexus.security.user.UserNotFoundException e) {
user = security.addUser(userName, firstName, lastName, email, true, password, ["deployer"])
}
nuGetApiKey = getOrCreateNuGetApiKey(userName)
}
addDeployerUser("Jenkins", "Doe", "jenkins@example.com", "jenkins", jenkinsPassword)
addDeployerUser("Alice", "Doe", "alice.doe@example.com", "alice.doe", "password")
addDeployerUser("Bob", "Doe", "bob.doe@example.com", "bob.doe", "password")
// get the jenkins NuGet API Key.
jenkinsNuGetApiKey = getOrCreateNuGetApiKey("jenkins")
realms = realmManager.getConfiguration().getRealmNames()
users = security.securitySystem.searchUsers(new UserSearchCriteria())
repositories = repository.repositoryManager.browse().collect { [name:it.name,type:it.type.value] }
return JsonOutput.toJson([
/*tasksDescriptors: taskScheduler.taskFactory.descriptors.collect { [
id: it.id,
name: it.name,
exposed: it.exposed,
formFields: it.formFields?.collect { [
id: it.id,
type: it.type,
label: it.label,
helpText: it.helpText,
required: it.required,
regexValidation: it.regexValidation,
initialValue: it.initialValue,
] }
] },*/
realms: realms.sort { it },
users: users.sort { it.userId },
repositories: repositories.sort { it.name },
])

186
provision/provision.sh Normal file
View File

@ -0,0 +1,186 @@
#!/bin/bash
# here be dragons... see http://fvue.nl/wiki/Bash:_Error_handling
set -eux
config_fqdn=$(hostname --fqdn)
config_domain=$(hostname --domain)
echo "127.0.0.1 $config_fqdn" >>/etc/hosts
# update the package cache.
apt-get -y update
# vim.
apt-get install -y --no-install-recommends vim
cat >/etc/vim/vimrc.local <<'EOF'
syntax on
set background=dark
set esckeys
set ruler
set laststatus=2
set nobackup
autocmd BufNewFile,BufRead Vagrantfile set ft=ruby
EOF
# create a self-signed certificate.
pushd /etc/ssl/private
openssl genrsa \
-out $config_fqdn-keypair.pem \
2048 \
2>/dev/null
chmod 400 $config_fqdn-keypair.pem
openssl req -new \
-sha256 \
-subj "/CN=$config_fqdn" \
-key $config_fqdn-keypair.pem \
-out $config_fqdn-csr.pem
openssl x509 -req -sha256 \
-signkey $config_fqdn-keypair.pem \
-extensions a \
-extfile <(echo "[a]
subjectAltName=DNS:$config_fqdn
extendedKeyUsage=serverAuth
") \
-days 365 \
-in $config_fqdn-csr.pem \
-out $config_fqdn-crt.pem
popd
# install and configure nginx to proxy to nexus.
# see https://books.sonatype.com/nexus-book/3.0/reference/install.html#reverse-proxy
apt-get install -y --no-install-recommends nginx
rm -f /etc/nginx/sites-enabled/default
cat<<EOF>/etc/nginx/sites-available/$config_fqdn.conf
ssl_session_cache shared:SSL:4m;
ssl_session_timeout 6h;
#ssl_stapling on;
#ssl_stapling_verify on;
server {
listen 80;
server_name _;
return 301 https://$config_fqdn\$request_uri;
}
server {
listen 443 ssl http2;
server_name $config_fqdn;
access_log /var/log/nginx/$config_fqdn.access.log;
ssl_certificate /etc/ssl/private/$config_fqdn-crt.pem;
ssl_certificate_key /etc/ssl/private/$config_fqdn-keypair.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# see https://github.com/cloudflare/sslconfig/blob/master/conf
# see https://blog.cloudflare.com/it-takes-two-to-chacha-poly/
# see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
# NB even though we have CHACHA20 here, the OpenSSL library that ships with Ubuntu 16.04 does not have it. so this is a nop. no problema.
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!aNULL:!MD5;
tcp_nodelay on;
client_max_body_size 1G;
proxy_send_timeout 120;
proxy_read_timeout 300;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
location / {
root /opt/nexus/public;
try_files \$uri @nexus;
}
location @nexus {
proxy_pass http://127.0.0.1:8081;
}
}
EOF
ln -s ../sites-available/$config_fqdn.conf /etc/nginx/sites-enabled/
systemctl restart nginx
# install java.
apt-get install -y default-jre
# add the nexus user.
groupadd --system nexus
adduser \
--system \
--disabled-login \
--no-create-home \
--gecos '' \
--ingroup nexus \
--home /opt/nexus \
nexus
install -d -o root -g nexus -m 750 /opt/nexus
# download and install nexus.
pushd /opt/nexus
# see http://www.sonatype.com/download-oss-sonatype
# see https://books.sonatype.com/nexus-book/3.0/reference/index.html
nexus_tarball=nexus-3.1.0-04-unix.tar.gz
nexus_download_url=https://sonatype-download.global.ssl.fastly.net/nexus/3/$nexus_tarball
nexus_download_sha1=e42053ba8ab33b3b4f79f7e50dbac2ffe6ca3b6e
wget -q $nexus_download_url
if [ "$(sha1sum $nexus_tarball | awk '{print $1}')" != "$nexus_download_sha1" ]; then
echo "downloaded $nexus_download_url failed the checksum verification"
exit 1
fi
tar xf $nexus_tarball --strip-components 1
rm $nexus_tarball
chmod 700 nexus3
chown -R nexus:nexus nexus3
chmod 700 etc
chown -R nexus:nexus etc # for some reason karaf changes files inside this directory. TODO see why.
install -d -o nexus -g nexus -m 700 .java # java preferences are saved here (the default java.util.prefs.userRoot preference).
cp -p etc/{nexus-default.properties,nexus.properties}
sed -i -E 's,(application-host=).+,\1127.0.0.1,g' etc/nexus.properties
sed -i -E 's,nexus-pro-,nexus-oss-,g' etc/nexus.properties
sed -i -E 's,\.\./sonatype-work/,,g' bin/nexus.vmoptions
popd
# start nexus.
cat >/etc/systemd/system/nexus.service <<'EOF'
[Unit]
Description=Nexus
After=network.target
[Service]
Type=simple
User=nexus
Group=nexus
ExecStart=/opt/nexus/bin/nexus run
WorkingDirectory=/opt/nexus
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable nexus
systemctl start nexus
# install tools.
apt-get install -y --no-install-recommends httpie
apt-get install -y --no-install-recommends jq
# wait for nexus to come up.
bash -c 'while [[ "$(wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq -r .data.data.status.value.edition)" != "OSS" ]]; do sleep 5; done'
# print the version using the API.
wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq --raw-output .data.data.uiSettings.value.title
wget -qO- http://localhost:8081/service/extdirect/poll/rapture_State_get | jq .data.data.status.value
# configure nexus with the groovy script.
bash /vagrant/provision/execute-provision.groovy-script.sh
# clean packages.
apt-get -y autoremove
apt-get -y clean

18
provision/summary.sh Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash
set -eux
config_fqdn=$(hostname --fqdn)
# show the installation summary.
cat <<EOF
nexus is running at:
http://localhost:8081
https://$config_fqdn
use the admin/admin123 credentials to login.
the logs are at:
/opt/nexus/data/log/
EOF

174
provision/test.sh Normal file
View File

@ -0,0 +1,174 @@
#!/bin/bash
set -eux
. /vagrant/provision/nexus-groovy.sh
mkdir -p tmp && cd tmp
#
# test the NuGet repository.
# see https://books.sonatype.com/nexus-book/3.0/reference/nuget.html
if ! which mono; then
sudo apt-get install -y mono-complete
fi
if [[ ! -f /tmp/nuget.exe ]]; then
wget -qO/tmp/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
fi
function nuget {
mono /tmp/nuget.exe $*
}
nuget_source_url=http://localhost:8081/repository/nuget-group/
nuget_source_push_url=http://localhost:8081/repository/nuget-hosted/
nuget_source_push_api_key=$(nexus-groovy get-jenkins-nuget-api-key | jq -r '.result | fromjson | .apiKey')
# test installing a package from the public NuGet repository.
nuget install MsgPack -Source $nuget_source_url
# test publishing a package.
cat <<'EOF' >example-hello-world.nuspec
<package>
<metadata>
<id>example-hello-world</id>
<version>1.0.0</version>
<authors>Alice Doe</authors>
<owners>Bob Doe</owners>
<licenseUrl>http://choosealicense.com/licenses/mit/</licenseUrl>
<projectUrl>http://example.com</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Example Package Description</description>
<releaseNotes>Hello World.</releaseNotes>
<copyright>Copyleft Alice Doe</copyright>
<tags>hello world</tags>
</metadata>
<files>
<file src="MESSAGE.md" target="content" />
</files>
</package>
EOF
cat <<'EOF' >MESSAGE.md
# Hello World
Hey Ho Let's Go!
EOF
nuget pack example-hello-world.nuspec
nuget push example-hello-world.1.0.0.nupkg -Source $nuget_source_push_url -ApiKey $nuget_source_push_api_key
# test installing it back.
rm -rf test && mkdir test && pushd test
nuget install example-hello-world -Source $nuget_source_url
if [[ ! -f example-hello-world.1.0.0/content/MESSAGE.md ]]; then
echo 'the package did not install as expected'
exit 1
fi
popd
#
# test the maven repository.
# install maven and the java development kit.
sudo apt-get install -y maven
sudo apt-get install -y default-jdk
sudo apt-get install -y xmlstarlet
# setup the user maven configuration to use nexus as a mirror the
# official maven repository.
# see https://books.sonatype.com/nexus-book/3.0/reference/maven.html
# see https://maven.apache.org/guides/mini/guide-mirror-settings.html
mkdir -p ~/.m2
cat <<'EOF' >~/.m2/settings.xml
<settings>
<servers>
<server>
<id>nexus</id>
<username>alice.doe</username>
<password>password</password>
</server>
</servers>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>central</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
EOF
# test our nexus repository by creating an hello world project, which
# will pull from our nexus repository.
mvn \
archetype:generate \
-DgroupId=com.example.helloworld \
-DartifactId=example-helloworld \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
# test publishing a package.
pushd example-helloworld
# add the nexus repository to pom.xml.
xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \
--subnode '/pom:project' \
--type elem \
--name distributionManagement \
--value '@@repositories@@' \
pom.xml
python -c '
xml = open("pom.xml").read().replace("@@repositories@@", """
<repository>
<id>nexus</id>
<name>Releases</name>
<url>http://localhost:8081/repository/maven-releases</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<name>Snapshot</name>
<url>http://localhost:8081/repository/maven-snapshots</url>
</snapshotRepository>
""")
open("pom.xml", "w").write(xml)
'
# deploy.
mvn deploy
popd
#
# test the raw repository.
apt-get install -y curl
# upload.
# see https://books.sonatype.com/nexus-book/3.0/reference/raw.html#_uploading_files_to_hosted_raw_repositories
expected='this is an adhoc package'
echo "$expected" >package-1.0.0.txt
curl --silent --user 'admin:admin123' --upload-file package-1.0.0.txt http://localhost:8081/repository/adhoc-package/package-1.0.0.txt
# download.
actual=$(curl --silent http://localhost:8081/repository/adhoc-package/package-1.0.0.txt)
[ "$actual" = "$expected" ] || (echo 'upload adhoc package test failed' && false)