Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Nomulus is an open source, scalable, cloud-based service for operating
[top-level domains](https://en.wikipedia.org/wiki/Top-level_domain) (TLDs). It
is the authoritative source for the TLDs that it runs, meaning that it is
responsible for tracking domain name ownership and handling registrations,
renewals, availability checks, and WHOIS requests. End-user registrants (i.e.,
renewals, availability checks, and RDAP requests. End-user registrants (i.e.,
people or companies that want to register a domain name) use an intermediate
domain name registrar acting on their behalf to interact with the registry.

Expand Down Expand Up @@ -97,7 +97,7 @@ Nomulus has the following capabilities:
for details), and an implementation based on
[Google Cloud Secret Manager](https://cloud.google.com/security/products/secret-manager) is
available.
* **TPC Proxy**: Nomulus is built on top of the [Jetty](https://jetty.org/)
* **TCP Proxy**: Nomulus is built on top of the [Jetty](https://jetty.org/)
container that implements the [Jakarta Servlet](https://jakarta.ee/specifications/servlet/)
specification and only serves HTTP/S traffic. A proxy to translate raw TCP traffic (e.g., EPP)
to and from HTTP is provided.
Expand Down
9 changes: 4 additions & 5 deletions console-webapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ expected to change.

## Deployment

The webapp is deployed with the nomulus default service war to GKE.
During nomulus default service war build task, gradle script triggers the
following:
The webapp is deployed as part of the default Nomulus GKE service image.
During the image build task, the Gradle script triggers the following:

1) Console webapp build script `buildConsoleWebapp`, which installs
dependencies, assembles a compiled ts -> js, minified, optimized static
artifact (html, css, js)
2) Artifact assembled in step 1 then gets copied to core project web artifact
location, so that it can be deployed with the rest of the core webapp
2) Artifact assembled in step 1 then gets copied to the jetty webapp resource
location, so that it can be staged inside the default GKE service container.

## Development server

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,16 +266,6 @@
<schedule>0 15 * * *</schedule>
</task>

<task>
<url><![CDATA[/_dr/task/wipeOutContactHistoryPii]]></url>
<name>wipeOutContactHistoryPii</name>
<description>
This job runs weekly to wipe out PII fields of ContactHistory entities
that have been in the database for a certain period of time.
</description>
<schedule>0 15 * * 1</schedule>
</task>

<task>
<url><![CDATA[/_dr/task/bsaDownload]]></url>
<name>bsaDownload</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,6 @@
<schedule>*/1 * * * *</schedule>
</task>

<task>
<url><![CDATA[/_dr/task/wipeOutContactHistoryPii]]></url>
<name>wipeOutContactHistoryPii</name>
<description>
This job runs weekly to wipe out PII fields of ContactHistory entities
that have been in the database for a certain period of time.
</description>
<schedule>0 15 * * 1</schedule>
</task>

<task>
<url><![CDATA[/_dr/task/bsaDownload]]></url>
<name>bsaDownload</name>
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/java/google/registry/webdriver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ for more information on using webdriver.
2. Missing golden images
* If you added a new test using screenshot comparison, you have to generate
the golden image for that test in advance and copy it to
[goldens/](https://github.com/google/nomulus/tree/master/core/src/test/java/google/registry/webdriver/goldens)
[goldens/](https://github.com/google/nomulus/tree/master/core/src/test/resources/google/registry/webdriver/goldens)
folder. There
is an auxiliary Gradle build task to help with this, and here are some examples:
```shell
Expand Down
77 changes: 69 additions & 8 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ Here are the task queues in use by the system:
run infrequently, such as exporting reserved terms.
* `sheet` -- Queue for tasks to sync registrar updates to a Google Sheets
spreadsheet, done by `SyncRegistrarsSheetAction`.
* `async-actions` -- Queue for general asynchronous actions that should be run at
some point in the future.
* `async-host-rename` -- Queue for tasks that trigger domain DNS updates upon
host renaming.
* `beam-reporting` -- Queue for tasks that wait for a Beam pipeline (such as
Spec11 reporting or invoicing) to complete.
* `console-user-group-update` -- Queue for tasks that update membership in the
Google Groups for console users.

### Scheduled cron jobs

Expand All @@ -113,13 +121,65 @@ minute (in the case of syncing DNS updates) or as infrequently as once per month
are more tasks that run in Production than in other environments because tasks
like uploading RDE dumps are only done for the live system.

Here are the primary cron tasks configured in the production environment:

* **`rdeStaging`** (`/_dr/task/rdeStaging`) -- Generates a full RDE escrow
deposit as a single large XML document and streams it to Google Cloud
Storage daily.
* **`rdeUpload`** (`/_dr/task/rdeUpload`) -- Uploads already-generated RDE
files from GCS to the escrow provider (e.g. Iron Mountain) via SFTP.
* **`rdeReport`** (`/_dr/task/rdeReport`) -- Uploads RDE reports to ICANN.
* **`tmchDnl`**, **`tmchSmdrl`**, **`tmchCrl`** (`/_dr/task/tmchDnl`,
`tmchSmdrl`, `tmchCrl`) -- Download the latest Domain Name Label list,
Signed Mark Revocation List, and Certificate Revocation List from MarksDB
and update the registry database.
* **`syncGroupMembers`** (`/_dr/task/syncGroupMembers`) -- Syncs registrar
contact changes from the database to Google Groups.
* **`syncRegistrarsSheet`** (`/_dr/task/syncRegistrarsSheet`) -- Synchronizes
registrar entities to a Google Sheets spreadsheet for business visibility.
* **`updateRegistrarRdapBaseUrls`** (`/_dr/task/updateRegistrarRdapBaseUrls`)
-- Reloads all registrar RDAP base URLs from ICANN.
* **`exportDomainLists`** (`/_dr/task/exportDomainLists`) -- Exports active
domain lists to GCS and Google Drive.
* **`expandBillingRecurrences`** (`/_dr/task/expandBillingRecurrences`) --
Generates synthetic one-time billing events from recurring billing setup.
* **`deleteExpiredDomains`** (`/_dr/task/deleteExpiredDomains`) -- Deletes
domains that are past their auto-renew end date daily.
* **`sendExpiringCertificateNotificationEmail`**
(`/_dr/task/sendExpiringCertificateNotificationEmail`) -- Notifies
registrars of upcoming SSL certificate expirations.
* **`nordnUploadSunrise`**, **`nordnUploadClaims`** (`/_dr/task/nordnUpload`)
-- Upload LORDN Sunrise/Claims CSV files to MarksDB.
* **`deleteProberData`** (`/_dr/task/deleteProberData`) -- Daily cleanup of
test data generated by probers.
* **`exportReservedTerms`**, **`exportPremiumTerms`**
(`/_dr/task/exportReservedTerms`, `exportPremiumTerms`) -- Export reserved
and premium terms to Google Drive.
* **`readDnsRefreshRequests`** (`/_dr/task/readDnsRefreshRequests`) -- Reads
DNS refresh requests from the database and batches them to the publish queue
every minute.
* **`icannReportingStaging`**, **`icannReportingUpload`**
(`/_dr/task/icannReportingStaging`, `icannReportingUpload`) -- Stage monthly
ICANN activity/transaction reports and upload them.
* **`generateInvoices`** (`/_dr/task/generateInvoices`) -- Starts Dataflow
templates to generate monthly billing invoices.
* **`generateSpec11`** (`/_dr/task/generateSpec11`) -- Starts Dataflow
templates to generate daily Spec11 anti-abuse reports.
* **`bsaDownload`**, **`bsaRefresh`**, **`bsaValidate`**,
**`uploadBsaUnavailableNames`** -- Download block lists, refresh registered
names, validate data, and upload unavailable names for the Brand Safety
Alliance (BSA) service.
* **`triggerMosApiServiceState`** (`/_dr/task/triggerMosApiServiceState`) --
Fetches the service state from MosAPI and triggers metrics status for all
TLDs every 5 minutes.

Most cron tasks use the `TldFanoutAction` which is accessed via the
`/_dr/cron/fanout` URL path. This action fans out a given cron task for each TLD
that exists in the registry system, using the queue that is specified in the XML
entry. Because some tasks may be computationally intensive and could risk
spiking system latency if all start executing immediately at the same time,
spiking system latency if all start executing immediately at the same time,
there is a `jitterSeconds` parameter that spreads out tasks over the given
number of seconds. This is used with DNS updates and commit log deletion.
number of seconds. This is used with DNS updates.

The reason the `TldFanoutAction` exists is that a lot of tasks need to be done
separately for each TLD, such as RDE exports and NORDN uploads. It's simpler to
Expand All @@ -130,8 +190,9 @@ failures that a raw cron task does not. This is why there are some tasks that do
not fan out across TLDs that still use `TldFanoutAction` -- it's so that the
tasks retry in the face of transient errors.

The full list of URL parameters to `TldFanoutAction` that can be specified in
cron.xml is:
The full list of URL parameters to `TldFanoutAction` that can be specified in the
Cloud Scheduler configuration files (such as
`cloud-scheduler-tasks-production.xml`) is:

* `endpoint` -- The path of the action that should be executed
* `queue` -- The cron queue to enqueue tasks in.
Expand All @@ -156,7 +217,7 @@ which includes a separate database and separate bulk storage in Cloud Storage.
Each environment is thus completely independent.

The different environments are specified in `RegistryEnvironment`. Most
correspond to a separate App Engine app except for `UNITTEST` and `LOCAL`, which
correspond to a separate GCP project except for `UNITTEST` and `LOCAL`, which
by their nature do not use real environments running in the cloud. The
recommended project naming scheme that has the best possible compatibility with
the codebase and thus requires the least configuration is to pick a name for the
Expand Down Expand Up @@ -185,14 +246,14 @@ real to not-real, is:
the entire system down until it is completed) without affecting the QA
environment.
* `ALPHA` -- The developers' playground. Experimental builds are routinely
pushed here in order to test them on a real app running on App Engine. You
pushed here in order to test them on a real GKE cluster running in GCP. You
may end up wanting multiple environments like Alpha if you regularly
experience contention (i.e. developers being blocked from testing their code
on Alpha because others are already using it).
* `LOCAL` -- A fake environment that is used when running the app locally on a
simulated App Engine instance.
simulated instance.
* `UNITTEST` -- A fake environment that is used in unit tests, where
everything in the App Engine stack is simulated or mocked.
everything in the cloud stack is simulated or mocked.

## Release process

Expand Down
19 changes: 10 additions & 9 deletions docs/authentication-framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,13 @@ architecture -- an `Authorization` HTTP header of the form "Bearer: XXXX".

### Configuration

The `auth` block of the configuration requires two fields: *
`allowedServiceAccountEmails` is the list of service accounts that should be
allowed to run tasks when internally authenticated. This will likely include
whatever service account runs Nomulus in Google Kubernetes Engine, as well as
the Cloud Scheduler service account. * `oauthClientId` is the OAuth client ID
associated with IAP. This is retrievable from the
[Clients page](https://pantheon.corp.google.com/auth/clients) of GCP after
enabling the Identity-Aware Proxy. It should look something like
`someNumbers-someNumbersAndLetters.apps.googleusercontent.com`
The `auth` block of the configuration requires two fields:

* `allowedServiceAccountEmails` is the list of service accounts that should be
allowed to run tasks when internally authenticated. This will likely include
whatever service account runs Nomulus in Google Kubernetes Engine, as well
as the Cloud Scheduler service account.
* `oauthClientId` is the OAuth client ID associated with IAP. This is retrievable
from the [Clients page](https://pantheon.corp.google.com/auth/clients) of GCP
after enabling the Identity-Aware Proxy. It should look something like
`someNumbers-someNumbersAndLetters.apps.googleusercontent.com`
17 changes: 12 additions & 5 deletions docs/code-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ versions stored in the various `gradle.lockfile` files. To update these
versions, run any Gradle command (e.g. `./gradlew build`) with the
`--write-locks` argument.

### Generating WAR archives for deployment
### Generating Docker images for deployment

The `jetty` project is the main entry point for building the Nomulus WAR files,
and one can use the `war` gradle task to build the base WAR file. The various
deployment/release files use Docker to deploy this, in a system that is too
Google-specialized to replicate directly here.
The `jetty` project is the main entry point for building the Nomulus Docker
images. You can use the `./gradlew :jetty:buildNomulusImage` task to build the
image locally, which contains the compiled WAR files and Angular assets staged
inside a Jetty base image. You can use `./gradlew :jetty:pushNomulusImage` to
push this image to your GCR/Artifact Registry repository.

## Subprojects

Expand Down Expand Up @@ -68,6 +69,12 @@ The following cursor types are defined:
events into one-time `BillingEvent`s.
* **`SYNC_REGISTRAR_SHEET`** - Tracks the last time the registrar spreadsheet
was successfully synced.
* **`ICANN_UPLOAD_TX`** - Tracks monthly uploads of ICANN transaction reports.
* **`ICANN_UPLOAD_ACTIVITY`** - Tracks monthly uploads of ICANN activity reports.
* **`REMOTE_CACHE_DOMAIN_SYNC`** - Tracks the reflection of domain changes in
the remote cache.
* **`REMOTE_CACHE_HOST_SYNC`** - Tracks the reflection of host changes in
the remote cache.

All `Cursor` entities in the database contain a `DateTime` that represents the
next timestamp at which an operation should resume processing and a `CursorType`
Expand Down
49 changes: 25 additions & 24 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,19 @@ For the Nomulus tool OAuth configuration, do the following steps:
`registryTool` section. This will make the `nomulus` tool use this
credential to authenticate itself to the system.

For IAP configuration, do the following steps: * **Create the IAP client ID:**
Follow similar steps from above to create an additional OAuth client ID, but
using an application type of "Web application". Note the client ID and secret. *
**Enable IAP for your HTTPS load balancer:** On the
[IAP page](https://pantheon.corp.google.com/security/iap), enable IAP for all of
the backend services that all use the same HTTPS load balancer. * **Use a custom
OAuth configuration:** For the backend services, under the "Settings" section
(in the three-dot menu) enable custom OAuth and insert the client ID and secret
that we just created * **Save the client ID:** In the configuration file, save
the client ID as `oauthClientId` in the `auth` section
For IAP configuration, do the following steps:

* **Create the IAP client ID:** Follow similar steps from above to create an
additional OAuth client ID, but using an application type of "Web
application". Note the client ID and secret.
* **Enable IAP for your HTTPS load balancer:** On the
[IAP page](https://pantheon.corp.google.com/security/iap), enable IAP for
all of the backend services that all use the same HTTPS load balancer.
* **Use a custom OAuth configuration:** For the backend services, under the
"Settings" section (in the three-dot menu), enable custom OAuth and
insert the client ID and secret that we just created.
* **Save the client ID:** In the configuration file, save the client ID as
`oauthClientId` in the `auth` section.

Once these steps are taken, the `nomulus` tool and IAP will both use client IDs
which the server is configured to accept, and authentication should succeed.
Expand Down Expand Up @@ -171,9 +174,8 @@ To create or update TLDs, we use
configure_tld` command. Because the TLDs are stored as data in the running
system, they do not require code pushes to update.

[app-engine-config]: https://cloud.google.com/appengine/docs/java/configuration-files
[default-config]: https://github.com/google/nomulus/blob/master/java/google/registry/config/files/default-config.yaml
[registry-config]: https://github.com/google/nomulus/blob/master/java/google/registry/config/RegistryConfig.java
[default-config]: https://github.com/google/nomulus/blob/master/core/src/main/java/google/registry/config/files/default-config.yaml
[registry-config]: https://github.com/google/nomulus/blob/master/core/src/main/java/google/registry/config/RegistryConfig.java

## Cloud SQL Configuration

Expand Down Expand Up @@ -244,9 +246,9 @@ something similar. However, for purposes of this exercise we will push the
schema from the build system.

First, download the
[Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy). This will
allow you to connect to your database from a local workstation without a lot of
additional configuration.
[Cloud SQL Auth Proxy](https://cloud.google.com/sql/docs/postgres/sql-proxy).
This will allow you to connect to your database from a local workstation without
a lot of additional configuration.

Create a service account for use with the proxy:

Expand Down Expand Up @@ -277,12 +279,11 @@ Now start the proxy:

```
$ PORT=3306 # Use a different value for this if you like.
$ ./cloud_sql_proxy -credential_file=sql-admin.json \
-instances=$PROJECT_ID:nomulus=tcp:$PORT
2020/07/01 12:11:20 current FDs rlimit set to 32768, wanted limit is 8500. Nothing to do here.
2020/07/01 12:11:20 using credential file for authentication; email=sql-proxy@pproject-id.iam.gserviceaccount.com
2020/07/01 12:11:20 Listening on 127.0.0.1:3306 for project-id:nomulus
2020/07/01 12:11:20 Ready for new connections
$ ./cloud-sql-proxy --credentials-file=sql-admin.json --port=$PORT \
$PROJECT_ID:us-central1:nomulus
2026/06/16 12:11:20 Authorizing with credentials file: sql-admin.json
2026/06/16 12:11:20 Listening on 127.0.0.1:3306 for project-id:us-central1:nomulus
2026/06/16 12:11:20 The proxy has started successfully and is ready for new connections!
```

Finally, upload the new database schema:
Expand Down Expand Up @@ -366,8 +367,8 @@ $ nomulus -e $ENV update_keyring_secret --keyname TOOLS_CLOUD_SQL_PASSWORD \
Use get_keyring_secret command to verify the data you put in:

```
$ nomulus -e alpha -e alpha get_keyring_secret --keyname CLOUD_SQL_PASSWORD
$ nomulus -e alpha get_keyring_secret --keyname CLOUD_SQL_PASSWORD
[your password]
$ nomulus -e alpha -e alpha get_keyring_secret --keyname CLOUD_SQL_PASSWORD
$ nomulus -e alpha get_keyring_secret --keyname TOOLS_CLOUD_SQL_PASSWORD
[your password]
```
Loading
Loading