Compare commits

...

12 Commits

13 changed files with 567 additions and 211 deletions

View File

@ -2,12 +2,15 @@ This is a Vagrant Environment for a [Nexus Repository OSS](https://github.com/so
This will: This will:
* Configure Nexus through Groovy scripts. * Configure Nexus through the API.
* Create the `adhoc-package` repository. * Create the `adhoc-package` repository.
* Create the `apt-hosted` repository.
* Create the `npm-group`, `npm-hosted` and `npmjs.org-proxy` repositories. * Create the `npm-group`, `npm-hosted` and `npmjs.org-proxy` repositories.
* Create the `chocolatey-group`, `chocolatey-hosted` and `chocolatey.org-proxy` repositories.
* Create the `powershell-group`, `powershell-hosted` and `powershellgallery.com-proxy` repositories. * Create the `powershell-group`, `powershell-hosted` and `powershellgallery.com-proxy` repositories.
* Create the `chocolatey-group`, `chocolatey-hosted` and `chocolatey.org-proxy` repositories.
* Create the `docker-group`, `docker-hosted` and `docker-hub-proxy` repositories.
* Configure the NuGet `nuget-hosted` repository to accept pushing with an API key. * Configure the NuGet `nuget-hosted` repository to accept pushing with an API key.
* Configure Nexus through Groovy scripts.
* Schedule a task to remove the old snapshots from the `maven-snapshots` repository. * Schedule a task to remove the old snapshots from the `maven-snapshots` repository.
* Create users and a custom `deployer` role. * Create users and a custom `deployer` role.
* Setup an Active Directory LDAP user authentication source (when `config_authentication='ldap'` is set inside the `provision-nexus.sh` file). * Setup an Active Directory LDAP user authentication source (when `config_authentication='ldap'` is set inside the `provision-nexus.sh` file).
@ -108,36 +111,53 @@ The logs are at `/opt/nexus/log/nexus.log`.
You can also see them with `journalctl -u nexus`. You can also see them with `journalctl -u nexus`.
## OrientDB ## H2 Database
Nexus uses [OrientDB](https://en.wikipedia.org/wiki/OrientDB) as its database. To directly use it from the console run: Nexus uses [H2 Database](https://en.wikipedia.org/wiki/H2_(database)) as its database management system.
**NB** Nexus OSS can only use the H2 database management system.
**NB** Nexus Pro can use the H2 or PostgreSQL database management system.
The Web based H2 Database Console is available at https://nexus.example.com/h2-console with the following settings:
| Setting | Value |
|----------------|--------------------------------------------------|
| Saved Settings | Generic H2 (Embedded) |
| Setting Name | Generic H2 (Embedded) |
| Driver Class | org.h2.Driver |
| JDBC URL | jdbc:h2:/opt/nexus/sonatype-work/nexus3/db/nexus |
| User Name | _empty_ |
| Password | _empty_ |
You can also access the database cli shell as:
```bash ```bash
sudo su -l # switch to the root user. sudo su -l # switch to the root user.
systemctl stop nexus # make sure nexus is not running while you use the database. systemctl stop nexus # make sure nexus is not running while you use the database.
su -s /bin/bash nexus # switch to the nexus user. su -s /bin/bash nexus # switch to the nexus user.
nexus_home=/opt/nexus/nexus-3.58.1-02 # make sure you have the correct version here. nexus_home=/opt/nexus/nexus-3.75.1-01 # make sure you have the correct version here.
nexus_data=$nexus_home/../sonatype-work/nexus3 nexus_data="$(realpath $nexus_home/../sonatype-work/nexus3)"
function orientdb-console { function h2-shell {
java -jar $nexus_home/lib/support/nexus-orient-console.jar $* java \
-cp $nexus_home/system/com/h2database/h2/*/h2*.jar \
org.h2.tools.Shell \
-url jdbc:h2:$nexus_data/db/nexus
} }
cd $nexus_data h2-shell
ls -laF db | grep ^d # list the databases
orientdb-console # start the console.
``` ```
Then connect to one of the databases, e.g. to the `security` database: Then execute some commands and exit the console, e.g.:
```plain ```sql
connect plocal:db/security admin admin -- see https://h2database.com/html/commands.html
```
Then execute some commands and exit the orientdb console, e.g.:
```plain
help help
config show schemas;
list classes show tables;
show columns from security_user;
select * from security_user;
select * from api_key_v2;
select * from repository;
exit exit
``` ```
@ -153,24 +173,7 @@ And start nexus again:
systemctl start nexus systemctl start nexus
``` ```
For more information about the console see [Running the OrientDB Console](http://orientdb.com/docs/master/Tutorial-Run-the-console.html). For more information see the [available Command Line Tools](https://h2database.com/html/tutorial.html#command_line_tools).
## OrientDB Check Databases
Execute the commands from the OrientDB section to stop nexus, to enter the
nexus account and create the `orientdb-console` function, then:
```bash
# check the databases.
# NB use CHECK DATABASE -v to see the verbose log.
orientdb-console 'CONNECT PLOCAL:db/component admin admin; CHECK DATABASE;'
#orientdb-console 'CONNECT PLOCAL:db/component admin admin; REPAIR DATABASE;'
orientdb-console 'CONNECT PLOCAL:db/config admin admin; CHECK DATABASE;'
orientdb-console 'CONNECT PLOCAL:db/security admin admin; CHECK DATABASE;'
#orientdb-console 'CONNECT PLOCAL:db/OSystem admin admin; CONFIG; LIST CLASSES;' # XXX fails to connect. see https://groups.google.com/a/glists.sonatype.com/forum/#!topic/nexus-users/7dVofIwC5HM
```
Then start nexus.
## Reference ## Reference

View File

@ -1,32 +1,34 @@
bleach==6.0.0 backports.tarfile==1.2.0
build==0.10.0 build==1.2.2.post1
certifi==2023.7.22 certifi==2024.8.30
cffi==1.15.1 cffi==1.17.1
charset-normalizer==3.2.0 charset-normalizer==3.4.0
cryptography==41.0.2 cryptography==44.0.0
docutils==0.20.1 docutils==0.21.2
idna==3.4 idna==3.10
importlib-metadata==6.8.0 importlib_metadata==8.5.0
jaraco.classes==3.3.0 jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.8.0 jeepney==0.8.0
keyring==24.2.0 keyring==25.5.0
markdown-it-py==3.0.0 markdown-it-py==3.0.0
mdurl==0.1.2 mdurl==0.1.2
more-itertools==10.0.0 more-itertools==10.5.0
packaging==23.1 nh3==0.2.19
pkginfo==1.9.6 packaging==24.2
pycparser==2.21 pkginfo==1.12.0
Pygments==2.15.1 pycparser==2.22
pyproject_hooks==1.0.0 Pygments==2.18.0
readme-renderer==40.0 pyproject_hooks==1.2.0
requests==2.31.0 readme_renderer==44.0
requests==2.32.3
requests-toolbelt==1.0.0 requests-toolbelt==1.0.0
rfc3986==2.0.0 rfc3986==2.0.0
rich==13.4.2 rich==13.9.4
SecretStorage==3.3.3 SecretStorage==3.3.3
six==1.16.0 tomli==2.2.1
tomli==2.0.1 twine==6.0.1
twine==4.0.2 typing_extensions==4.12.2
urllib3==2.0.4 urllib3==2.2.3
webencodings==0.5.1 zipp==3.21.0
zipp==3.16.2

View File

@ -12,7 +12,7 @@ function nexus-groovy {
local delete_result=$(http \ local delete_result=$(http \
-a "$admin_username:$admin_password" \ -a "$admin_username:$admin_password" \
--ignore-stdin \ --ignore-stdin \
DELETE https://$nexus_domain/service/rest/v1/script/provision.groovy) DELETE https://$nexus_domain/service/rest/v1/script/provision.groovy)
local create_result=$(http \ local create_result=$(http \
-a "$admin_username:$admin_password" \ -a "$admin_username:$admin_password" \

View File

@ -130,10 +130,12 @@ server {
proxy_send_timeout 120; proxy_send_timeout 120;
proxy_read_timeout 300; proxy_read_timeout 300;
proxy_buffering off; proxy_buffering off;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host; location /h2-console/ {
proxy_set_header X-Forwarded-Host \$host; proxy_http_version 1.1;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_pass http://localhost:8082/;
proxy_redirect http://localhost:8082/ /h2-console/;
}
location / { location / {
root /opt/nexus/public; root /opt/nexus/public;
@ -141,6 +143,10 @@ server {
} }
location @nexus { location @nexus {
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;
proxy_pass http://127.0.0.1:8081; proxy_pass http://127.0.0.1:8081;
} }
} }

View File

@ -12,7 +12,7 @@ config_authentication='nexus'
# install java. # install java.
# see https://help.sonatype.com/repomanager3/product-information/system-requirements#SystemRequirements-Java # see https://help.sonatype.com/repomanager3/product-information/system-requirements#SystemRequirements-Java
apt-get install -y openjdk-8-jre-headless apt-get install -y openjdk-17-jre-headless
apt-get install -y gnupg apt-get install -y gnupg
@ -35,17 +35,17 @@ pushd /opt/nexus
# see https://help.sonatype.com/repomanager3/product-information/download/download-archives---repository-manager-3 # see https://help.sonatype.com/repomanager3/product-information/download/download-archives---repository-manager-3
# see https://help.sonatype.com/repomanager3/product-information/release-notes # see https://help.sonatype.com/repomanager3/product-information/release-notes
# see https://help.sonatype.com/repomanager3 # see https://help.sonatype.com/repomanager3
nexus_version=3.58.1-02 nexus_version=3.75.1-01
nexus_home=/opt/nexus/nexus-$nexus_version nexus_home=/opt/nexus/nexus-$nexus_version
nexus_tarball=nexus-$nexus_version-unix.tar.gz nexus_tarball=nexus-$nexus_version-unix.tar.gz
nexus_download_url=https://download.sonatype.com/nexus/3/$nexus_tarball nexus_download_url=https://download.sonatype.com/nexus/3/$nexus_tarball
nexus_download_sha1=99d0cb82471f2b39a6060369e77868dd1462b243 nexus_download_sha1=cfc9e7bdaeb1f1b9fb45aecc7a50821759c8b847
wget -q $nexus_download_url wget -q $nexus_download_url
if [ "$(sha1sum $nexus_tarball | awk '{print $1}')" != "$nexus_download_sha1" ]; then if [ "$(sha1sum $nexus_tarball | awk '{print $1}')" != "$nexus_download_sha1" ]; then
echo "downloaded $nexus_download_url failed the checksum verification" echo "downloaded $nexus_download_url failed the checksum verification"
exit 1 exit 1
fi fi
tar xf $nexus_tarball # NB this creates the $nexus_home (e.g. nexus-3.58.1-02) and sonatype-work directories. tar xf $nexus_tarball # NB this creates the $nexus_home (e.g. nexus-3.75.1-01) and sonatype-work directories.
rm $nexus_tarball rm $nexus_tarball
install -d -o nexus -g nexus -m 700 .java # java preferences are saved here (the default java.util.prefs.userRoot preference). install -d -o nexus -g nexus -m 700 .java # java preferences are saved here (the default java.util.prefs.userRoot preference).
install -d -o nexus -g nexus -m 700 sonatype-work/nexus3/etc install -d -o nexus -g nexus -m 700 sonatype-work/nexus3/etc
@ -65,6 +65,11 @@ nexus.security.randompassword=false
# see https://issues.sonatype.org/browse/NEXUS-23205 # see https://issues.sonatype.org/browse/NEXUS-23205
# see Scripting Nexus Repository Manager 3 at https://support.sonatype.com/hc/en-us/articles/360045220393 # see Scripting Nexus Repository Manager 3 at https://support.sonatype.com/hc/en-us/articles/360045220393
nexus.scripts.allowCreation=true nexus.scripts.allowCreation=true
# enable the database console.
# see https://support.sonatype.com/hc/en-us/articles/213467158-How-to-reset-a-forgotten-admin-password-in-Sonatype-Nexus-Repository-3#DatabaseConsoleforh2Database
nexus.h2.httpListenerEnabled=true
nexus.h2.httpListenerPort=8082
EOF EOF
diff -u $nexus_home/etc/nexus-default.properties sonatype-work/nexus3/etc/nexus.properties || true diff -u $nexus_home/etc/nexus-default.properties sonatype-work/nexus3/etc/nexus.properties || true
popd popd
@ -161,6 +166,142 @@ bash /vagrant/provision/execute-provision.groovy-script.sh
# set the api credentials. # set the api credentials.
api_auth="admin:admin" api_auth="admin:admin"
# create the adhoc-package raw repository.
# NB this repository can host any type of artifact, so we disable strictContentTypeValidation.
# see https://help.sonatype.com/display/NXRM3/Raw+Repositories+and+Maven+Sites#RawRepositoriesandMavenSites-UploadingFilestoHostedRawRepositories
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/raw/hosted \
<<'EOF'
{
"name": "adhoc-package",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": false,
"writePolicy": "allow_once"
},
"component": {
"proprietaryComponents": true
}
}
EOF
# create the apt-hosted apt repository.
# see https://help.sonatype.com/repomanager3/formats/apt-repositories
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/apt/hosted \
<<EOF
{
"name": "apt-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once"
},
"component": {
"proprietaryComponents": true
},
"apt": {
"distribution": "jammy"
},
"aptSigning": {
"keypair": $(cat /vagrant/shared/apt-hosted-private.key | jq --slurp --raw-input .),
"passphrase": "abracadabra"
}
}
EOF
# create the npm-hosted npm repository.
# see https://help.sonatype.com/display/NXRM3/Node+Packaged+Modules+and+npm+Registries
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/npm/hosted \
<<'EOF'
{
"name": "npm-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once"
},
"component": {
"proprietaryComponents": true
}
}
EOF
# create the npmjs.org-proxy npm proxy repository.
# see https://help.sonatype.com/display/NXRM3/Node+Packaged+Modules+and+npm+Registries
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/npm/proxy \
<<'EOF'
{
"name": "npmjs.org-proxy",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once"
},
"proxy": {
"remoteUrl": "https://registry.npmjs.org",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true
}
}
EOF
# create the npm-group npm group repository.
# see https://help.sonatype.com/display/NXRM3/Node+Packaged+Modules+and+npm+Registries
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/npm/group \
<<'EOF'
{
"name": "npm-group",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"group": {
"memberNames": [
"npm-hosted",
"npmjs.org-proxy"
]
}
}
EOF
# create the pypi-hosted repository. # create the pypi-hosted repository.
http \ http \
--check-status \ --check-status \
@ -182,6 +323,282 @@ http \
} }
EOF EOF
# create the powershell-hosted nuget hosted repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/hosted \
<<'EOF'
{
"name": "powershell-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once"
},
"component": {
"proprietaryComponents": true
}
}
EOF
# create a powershellgallery.com-proxy powershell proxy repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/proxy \
<<'EOF'
{
"name": "powershellgallery.com-proxy",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"proxy": {
"remoteUrl": "https://www.powershellgallery.com/api/v2/",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"nugetProxy": {
"queryCacheItemMaxAge": 3600,
"nugetVersion": "V2"
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true
}
}
EOF
# create the powershell-group nuget group repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/group \
<<'EOF'
{
"name": "powershell-group",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"group": {
"memberNames": [
"powershell-hosted",
"powershellgallery.com-proxy"
]
}
}
EOF
# create the chocolatey-hosted nuget hosted repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/hosted \
<<'EOF'
{
"name": "chocolatey-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once"
},
"component": {
"proprietaryComponents": true
}
}
EOF
# create a chocolatey.org-proxy nuget proxy repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/proxy \
<<'EOF'
{
"name": "chocolatey.org-proxy",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"proxy": {
"remoteUrl": "https://chocolatey.org/api/v2/",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"nugetProxy": {
"queryCacheItemMaxAge": 3600,
"nugetVersion": "V2"
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true
}
}
EOF
# create the chocolatey-group nuget group repository.
# see https://help.sonatype.com/en/nuget-repositories.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/nuget/group \
<<'EOF'
{
"name": "chocolatey-group",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"group": {
"memberNames": [
"chocolatey-hosted",
"chocolatey.org-proxy"
]
}
}
EOF
# create the docker-hosted docker registry repository.
# see https://help.sonatype.com/en/docker-registry.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/docker/hosted \
<<'EOF'
{
"name": "docker-hosted",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true,
"writePolicy": "allow_once",
"latestPolicy": true
},
"component": {
"proprietaryComponents": true
},
"docker": {
"v1Enabled": false,
"forceBasicAuth": true,
"httpPort": 6003
}
}
EOF
# create the docker hub registry proxy repository.
# see https://help.sonatype.com/en/docker-registry.html
# NB as-of docker 19.03.5, there is still no way to specify a registry mirror credentials...
# as such, we cannot use our docker-group registry, instead we must use the docker-proxy
# registry, enable the Docker Bearer Token Realm and allow anonymous access to it.
# see https://github.com/moby/moby/issues/30880
# NB this will make https://nexus.example.com:5002/v2/library/debian/manifests/buster-slim proxy
# to https://registry-1.docker.io/v2/library/debian/manifests/buster-slim
# https://registry-1.docker.io/v2/library/golang/tags/list
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/docker/proxy \
<<'EOF'
{
"name": "docker-hub-proxy",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"proxy": {
"remoteUrl": "https://registry-1.docker.io",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true
},
"docker": {
"v1Enabled": false,
"forceBasicAuth": true,
"httpPort": 6002
},
"dockerProxy": {
"indexType": "HUB",
"cacheForeignLayers": true
}
}
EOF
# create the docker-group docker group repository.
# see https://help.sonatype.com/en/docker-registry.html
http \
--check-status \
--auth "$api_auth" \
POST \
https://$nexus_domain/service/rest/v1/repositories/docker/group \
<<'EOF'
{
"name": "docker-group",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"group": {
"memberNames": [
"docker-hosted",
"docker-hub-proxy"
]
},
"docker": {
"v1Enabled": false,
"forceBasicAuth": true,
"httpPort": 6001
}
}
EOF
# configure nexus ldap with a groovy script. # configure nexus ldap with a groovy script.
if [ "$config_authentication" = 'ldap' ]; then if [ "$config_authentication" = 'ldap' ]; then
bash /vagrant/provision/execute-provision-ldap.groovy-script.sh bash /vagrant/provision/execute-provision-ldap.groovy-script.sh

View File

@ -17,7 +17,7 @@ binaries: binaries-download
binaries-download: binaries-download:
mkdir -p binaries mkdir -p binaries
wget -qO- https://download.sonatype.com/nexus/3/nexus-3.58.1-02-unix.tar.gz \ wget -qO- https://download.sonatype.com/nexus/3/nexus-3.75.1-01-unix.tar.gz \
| tar xzf - --strip-components 1 -C binaries | tar xzf - --strip-components 1 -C binaries
clean: clean:

View File

@ -8,7 +8,7 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<properties> <properties>
<nx-version>3.58.1-02</nx-version> <nx-version>3.75.1-01</nx-version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@ -1,16 +0,0 @@
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

@ -6,7 +6,6 @@ import groovy.json.JsonOutput
import org.sonatype.nexus.capability.CapabilityRegistry import org.sonatype.nexus.capability.CapabilityRegistry
import org.sonatype.nexus.repository.config.WritePolicy import org.sonatype.nexus.repository.config.WritePolicy
import org.sonatype.nexus.security.user.UserSearchCriteria import org.sonatype.nexus.security.user.UserSearchCriteria
import org.sonatype.nexus.security.authc.apikey.ApiKeyStore
import org.sonatype.nexus.security.realm.RealmManager import org.sonatype.nexus.security.realm.RealmManager
import org.apache.shiro.subject.SimplePrincipalCollection import org.apache.shiro.subject.SimplePrincipalCollection
import org.sonatype.nexus.scheduling.TaskScheduler import org.sonatype.nexus.scheduling.TaskScheduler
@ -26,81 +25,6 @@ capabilityRegistry.all.findAll {it.context().type().toString().startsWith("Outre
// ]} // ]}
//]) //])
// create a raw repository backed by the default blob store.
// NB this repository can host any type of artifact, so we disable strictContentTypeValidation.
// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.x/scripting/complex-script/rawRepositories.groovy
// see https://help.sonatype.com/display/NXRM3/Raw+Repositories+and+Maven+Sites#RawRepositoriesandMavenSites-UploadingFilestoHostedRawRepositories
repository.createRawHosted("adhoc-package", "default", false, WritePolicy.ALLOW_ONCE)
// create a apt repository backed by the default blob store.
// see https://help.sonatype.com/repomanager3/formats/apt-repositories
pgpPrivateKey = new File('/vagrant/shared/apt-hosted-private.key').getText('UTF-8')
repository.createAptHosted("apt-hosted", "jammy", pgpPrivateKey, "abracadabra", "default", WritePolicy.ALLOW_ONCE, true)
// create a npm repository backed by the default blob store.
repository.createNpmHosted("npm-hosted", "default", true, WritePolicy.ALLOW_ONCE)
// create a npm proxy repository backed by the default blob store.
// see https://help.sonatype.com/display/NXRM3/Node+Packaged+Modules+and+npm+Registries
repository.createNpmProxy("npmjs.org-proxy", "https://registry.npmjs.org", "default")
// create a npm group repository that merges the npm-host and npmjs.org-proxy together.
repository.createNpmGroup("npm-group", ["npm-hosted", "npmjs.org-proxy"], "default")
// modify the default nuget-hosted repository for not allowing re-deployments.
config = repository.repositoryManager.get("nuget-hosted").configuration.copy()
config.attributes.storage.writePolicy = WritePolicy.ALLOW_ONCE
repository.repositoryManager.update(config)
// create a powershell repository backed by the default blob store.
repository.createNugetHosted("powershell-hosted", "default", true, WritePolicy.ALLOW_ONCE)
// create a powershell proxy repository backed by the default blob store.
// see https://help.sonatype.com/repomanager3/formats/nuget-repositories
config = repository.createNugetProxy("powershellgallery.com-proxy", "https://www.powershellgallery.com/api/v2/", "default").configuration.copy()
config.attributes.nugetProxy.nugetVersion = "V2"
repository.repositoryManager.update(config)
// create a powershell group repository that merges the powershell-host and powershellgallery.com-proxy together.
repository.createNugetGroup("powershell-group", ["powershell-hosted", "powershellgallery.com-proxy"], "default")
// create a chocolatey repository backed by the default blob store.
repository.createNugetHosted("chocolatey-hosted", "default", true, WritePolicy.ALLOW_ONCE)
// create a chocolatey proxy repository backed by the default blob store.
// see https://help.sonatype.com/repomanager3/formats/nuget-repositories
config = repository.createNugetProxy("chocolatey.org-proxy", "https://chocolatey.org/api/v2/", "default").configuration.copy()
config.attributes.nugetProxy.nugetVersion = "V2"
repository.repositoryManager.update(config)
// create a chocolatey group repository that merges the chocolatey-host and chocolatey.org-proxy together.
repository.createNugetGroup("chocolatey-group", ["chocolatey-hosted", "chocolatey.org-proxy"], "default")
// create a docker registry repository backed by the default blob store.
repository.createDockerHosted("docker-hosted", 6003, null, "default", true, true, WritePolicy.ALLOW, true)
// create a docker proxy repository backed by the default blob store.
// see https://help.sonatype.com/repomanager3/formats/docker-registry
// TODO set Allow Nexus Repository Manager to download and cache foreign layers.
// NB as-of docker 19.03.5, there is still no way to specify a registry mirror credentials...
// as such, we cannot use our docker-group registry, instead we must use the docker-proxy
// registry, enable the Docker Bearer Token Realm and allow anonymous access to it.
// see https://github.com/moby/moby/issues/30880
// NB this will make https://nexus.example.com:5002/v2/library/debian/manifests/buster-slim proxy
// to https://registry-1.docker.io/v2/library/debian/manifests/buster-slim
// https://registry-1.docker.io/v2/library/golang/tags/list
repository.createDockerProxy("docker-hub-proxy", "https://registry-1.docker.io", "HUB", null, 6002, null, "default", true, true, false)
// create a docker group repository that merges the docker-hosted and docker-hub-proxy together.
repository.createDockerGroup("docker-group", 6001, null, ["docker-hosted", "docker-hub-proxy"], true, "default", true)
// 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. // set the base url. this is used when sending emails.
// see https://help.sonatype.com/display/NXRM3/Configuration#Configuration-BaseURLCreation // see https://help.sonatype.com/display/NXRM3/Configuration#Configuration-BaseURLCreation
@ -121,7 +45,7 @@ taskConfiguration.setString("snapshotRetentionDays", "30")
taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next())) taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next()))
// NB you can list the available realms with realmManager.availableRealms. // enable the required realms.
realmManager = container.lookup(RealmManager.class.name) realmManager = container.lookup(RealmManager.class.name)
// enable the NuGet API-Key Realm. // enable the NuGet API-Key Realm.
realmManager.enableRealm("NuGetApiKey") realmManager.enableRealm("NuGetApiKey")
@ -141,20 +65,6 @@ security.anonymousAccess = true
// password is easier to remember. // password is easier to remember.
security.securitySystem.changePassword('admin', 'admin') security.securitySystem.changePassword('admin', 'admin')
// 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.name)
apiKey = keyStore.getApiKey(apiKeyDomain, principal)
if (apiKey == null) {
apiKey = keyStore.createApiKey(apiKeyDomain, principal)
}
return apiKey.toString()
}
// create users in the deployer role. // create users in the deployer role.
// see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.x/scripting/complex-script/security.groovy#L38 // see https://github.com/sonatype/nexus-book-examples/blob/nexus-3.x/scripting/complex-script/security.groovy#L38
@ -174,17 +84,11 @@ def addDeployerUser(firstName, lastName, email, userName, password) {
} catch (org.sonatype.nexus.security.user.UserNotFoundException e) { } catch (org.sonatype.nexus.security.user.UserNotFoundException e) {
user = security.addUser(userName, firstName, lastName, email, true, password, ["deployer"]) user = security.addUser(userName, firstName, lastName, email, true, password, ["deployer"])
} }
nuGetApiKey = getOrCreateNuGetApiKey(userName)
} }
addDeployerUser("Jenkins", "Doe", "jenkins@example.com", "jenkins", jenkinsPassword) addDeployerUser("Jenkins", "Doe", "jenkins@example.com", "jenkins", "password")
addDeployerUser("Alice", "Doe", "alice.doe@example.com", "alice.doe", "password") addDeployerUser("Alice", "Doe", "alice.doe@example.com", "alice.doe", "password")
addDeployerUser("Bob", "Doe", "bob.doe@example.com", "bob.doe", "password") addDeployerUser("Bob", "Doe", "bob.doe@example.com", "bob.doe", "password")
// get the jenkins NuGet API Key.
jenkinsNuGetApiKey = getOrCreateNuGetApiKey("jenkins")
realms = realmManager.configuration.realmNames
users = security.securitySystem.searchUsers(new UserSearchCriteria()) users = security.securitySystem.searchUsers(new UserSearchCriteria())
repositories = repository.repositoryManager.browse().collect { [name:it.name,type:it.type.value] } repositories = repository.repositoryManager.browse().collect { [name:it.name,type:it.type.value] }
@ -203,7 +107,6 @@ return JsonOutput.toJson([
initialValue: it.initialValue, initialValue: it.initialValue,
] } ] }
] },*/ ] },*/
realms: realms.sort { it },
users: users.sort { it.userId }, users: users.sort { it.userId },
repositories: repositories.sort { it.name }, repositories: repositories.sort { it.name },
]) ])

View File

@ -3,7 +3,9 @@ set -euxo pipefail
nexus_domain=$(hostname --fqdn) nexus_domain=$(hostname --fqdn)
mkdir -p tmp/use-maven-repository-from-gradle && cd tmp/use-maven-repository-from-gradle rm -rf tmp/use-maven-repository-from-gradle
mkdir -p tmp/use-maven-repository-from-gradle
cd tmp/use-maven-repository-from-gradle
# #
# test the maven repository from gradle. # test the maven repository from gradle.
@ -116,8 +118,8 @@ application {
mainClass = project.mainClassName mainClass = project.mainClassName
} }
sourceCompatibility = 1.8 sourceCompatibility = 17
targetCompatibility = 1.8 targetCompatibility = 17
jar { jar {
manifest { manifest {

View File

@ -3,14 +3,16 @@ set -euxo pipefail
nexus_domain=$(hostname --fqdn) nexus_domain=$(hostname --fqdn)
mkdir -p tmp/use-maven-repository-from-mvn && cd tmp/use-maven-repository-from-mvn rm -rf tmp/use-maven-repository-from-mvn
mkdir -p tmp/use-maven-repository-from-mvn
cd tmp/use-maven-repository-from-mvn
# #
# test the maven repository. # test the maven repository.
# install maven and the java development kit. # install maven and the java development kit.
sudo apt-get install -y maven sudo apt-get install -y maven
sudo apt-get install -y openjdk-8-jdk-headless sudo apt-get install -y openjdk-17-jdk-headless
sudo apt-get install -y xmlstarlet sudo apt-get install -y xmlstarlet
# setup the user maven configuration to use nexus as a mirror the # setup the user maven configuration to use nexus as a mirror the
@ -72,6 +74,14 @@ mvn \
# test publishing a package. # test publishing a package.
pushd example-helloworld pushd example-helloworld
# set the java version.
xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \
--subnode /pom:project --type elem --name properties \
pom.xml
xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \
--subnode /pom:project/pom:properties --type elem --name maven.compiler.source --value 17 \
--subnode /pom:project/pom:properties --type elem --name maven.compiler.target --value 17 \
pom.xml
# add the nexus repository to pom.xml. # add the nexus repository to pom.xml.
xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \ xmlstarlet ed --inplace -N pom=http://maven.apache.org/POM/4.0.0 \
--subnode '/pom:project' \ --subnode '/pom:project' \

View File

@ -3,7 +3,29 @@ set -euxo pipefail
nexus_domain=$(hostname --fqdn) nexus_domain=$(hostname --fqdn)
. /vagrant/provision/nexus-groovy.sh # see the requests made when using https://nexus.example.com/#user/nugetapitoken UI.
function get-jenkins-nuget-api-key {
local username='jenkins'
local password='password'
local user_token=$(http \
-a "$username:$password" \
--ignore-stdin \
--check-status \
POST https://$nexus_domain/service/extdirect \
action=rapture_Security \
method=authenticationToken \
type=rpc \
tid:=0 \
data:="[\"$(echo -n "$username" | base64 -w0)\",\"$(echo -n "$password" | base64 -w0)\"]" \
| jq -r .result.data)
http \
-a "$username:$password" \
--ignore-stdin \
--check-status \
GET https://$nexus_domain/service/rest/internal/nuget-api-key \
authToken=="$(echo -n "$user_token" | base64 -w0)" \
| jq -r .apiKey
}
mkdir -p tmp/use-nuget-repository && cd tmp/use-nuget-repository mkdir -p tmp/use-nuget-repository && cd tmp/use-nuget-repository
@ -19,7 +41,7 @@ fi
nuget_source_url=https://$nexus_domain/repository/nuget-group/index.json nuget_source_url=https://$nexus_domain/repository/nuget-group/index.json
nuget_source_push_url=https://$nexus_domain/repository/nuget-hosted/ nuget_source_push_url=https://$nexus_domain/repository/nuget-hosted/
nuget_source_push_api_key=$(nexus-groovy get-jenkins-nuget-api-key | jq -r '.result | fromjson | .apiKey') nuget_source_push_api_key=$(get-jenkins-nuget-api-key)
echo -n $nuget_source_push_api_key >/vagrant/shared/jenkins-nuget-api-key echo -n $nuget_source_push_api_key >/vagrant/shared/jenkins-nuget-api-key
nuget_source_push_api_key="$(cat /vagrant/shared/jenkins-nuget-api-key)" nuget_source_push_api_key="$(cat /vagrant/shared/jenkins-nuget-api-key)"

View File

@ -16,20 +16,27 @@ choco sources add --name nexus --source https://$nexusDomain/repository/chocolat
Write-Host 'Current Chocolatey sources:' Write-Host 'Current Chocolatey sources:'
choco sources list choco sources list
Write-Host 'Installing Google Chrome from the nexus server...' $browser = 'firefox'
# NB --ignore-checksums is needed because chrome does not release a versioned
# installer... as such, sometimes this package installation breaks if we
# do not ignore the checksums and there's a new chrome version available.
# see https://www.chromium.org/administrators/configuring-other-preferences
choco install -y --ignore-checksums googlechrome
$chromeLocation = 'C:\Program Files\Google\Chrome\Application'
cp -Force GoogleChrome-external_extensions.json (Resolve-Path "$chromeLocation\*\default_apps\external_extensions.json")
cp -Force GoogleChrome-master_preferences.json "$chromeLocation\master_preferences"
cp -Force GoogleChrome-master_bookmarks.html "$chromeLocation\master_bookmarks.html"
# set the default browser. if ($browser -eq 'firefox') {
choco install -y SetDefaultBrowser Write-Host 'Installing Firefox from the nexus server...'
SetDefaultBrowser HKLM "Google Chrome" choco install -y firefox --params 'l=en-US'
choco install -y SetDefaultBrowser
SetDefaultBrowser @((SetDefaultBrowser | Where-Object {$_ -like 'HKLM Firefox-*'}) -split ' ')
} else {
Write-Host 'Installing Google Chrome from the nexus server...'
# NB --ignore-checksums is needed because chrome does not release a versioned
# installer... as such, sometimes this package installation breaks if we
# do not ignore the checksums and there's a new chrome version available.
# see https://www.chromium.org/administrators/configuring-other-preferences
choco install -y --ignore-checksums googlechrome
$chromeLocation = 'C:\Program Files\Google\Chrome\Application'
cp -Force GoogleChrome-external_extensions.json (Resolve-Path "$chromeLocation\*\default_apps\external_extensions.json")
cp -Force GoogleChrome-master_preferences.json "$chromeLocation\master_preferences"
cp -Force GoogleChrome-master_bookmarks.html "$chromeLocation\master_bookmarks.html"
choco install -y SetDefaultBrowser
SetDefaultBrowser HKLM "Google Chrome"
}
# see https://github.com/chocolatey/choco/wiki/CreatePackages # see https://github.com/chocolatey/choco/wiki/CreatePackages
# see https://docs.nuget.org/docs/reference/nuspec-reference # see https://docs.nuget.org/docs/reference/nuspec-reference