mirror of
https://github.com/google/nomulus
synced 2026-07-26 10:03:23 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
853e571d01 | ||
|
|
9b79f5af2c | ||
|
|
4195871541 | ||
|
|
504d7ccaac | ||
|
|
36a8908712 | ||
|
|
e42c11051e | ||
|
|
85b588b51f | ||
|
|
572b7101cb | ||
|
|
445825957d | ||
|
|
7ab76f3573 |
@@ -347,6 +347,7 @@ subprojects {
|
||||
|
||||
def services = [':services:default',
|
||||
':services:backend',
|
||||
':services:bsa',
|
||||
':services:tools',
|
||||
':services:pubapi']
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import ContactComponent from './settings/contact/contact.component';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
import SecurityComponent from './settings/security/security.component';
|
||||
import UsersComponent from './settings/users/users.component';
|
||||
import { DomainListComponent } from './domains/domainList.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
@@ -35,6 +36,11 @@ const routes: Routes = [
|
||||
{ path: 'empty-registrar', component: EmptyRegistrar },
|
||||
{ path: 'home', component: HomeComponent, canActivate: [RegistrarGuard] },
|
||||
{ path: 'tlds', component: TldsComponent, canActivate: [RegistrarGuard] },
|
||||
{
|
||||
path: DomainListComponent.PATH,
|
||||
component: DomainListComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: SettingsComponent.PATH,
|
||||
component: SettingsComponent,
|
||||
|
||||
@@ -53,6 +53,7 @@ import {
|
||||
RegistrarDetailsComponent,
|
||||
RegistrarDetailsWrapperComponent,
|
||||
} from './registrar/registrarDetails.component';
|
||||
import { DomainListComponent } from './domains/domainList.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -60,6 +61,7 @@ import {
|
||||
BillingWidgetComponent,
|
||||
ContactDetailsDialogComponent,
|
||||
ContactWidgetComponent,
|
||||
DomainListComponent,
|
||||
DomainsWidgetComponent,
|
||||
EmptyRegistrar,
|
||||
EppWidgetComponent,
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<div class="console-domains">
|
||||
<mat-form-field>
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" #input />
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="isLoading; else domains_content" class="console-domains__loading">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
<ng-template #domains_content>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="domainName">
|
||||
<th mat-header-cell *matHeaderCellDef>Domain Name</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.domainName }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationTime">
|
||||
<th mat-header-cell *matHeaderCellDef>Creation Time</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
{{ element.creationTime.creationTime }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="registrationExpirationTime">
|
||||
<th mat-header-cell *matHeaderCellDef>Expiration Time</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
{{ element.registrationExpirationTime }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="statuses">
|
||||
<th mat-header-cell *matHeaderCellDef>Statuses</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.statuses }}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
|
||||
<!-- Row shown when there is no matching data. -->
|
||||
<tr class="mat-row" *matNoDataRow>
|
||||
<td class="mat-cell" colspan="4">No domains found</td>
|
||||
</tr>
|
||||
</table>
|
||||
<mat-paginator
|
||||
[length]="totalResults"
|
||||
[pageIndex]="pageNumber"
|
||||
[pageSize]="resultsPerPage"
|
||||
[pageSizeOptions]="[10, 25, 50, 100, 500]"
|
||||
(page)="onPageChange($event)"
|
||||
aria-label="Select page of domain results"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</ng-template>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DomainListComponent } from './domainList.component';
|
||||
|
||||
describe('DomainListComponent', () => {
|
||||
let component: DomainListComponent;
|
||||
let fixture: ComponentFixture<DomainListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [DomainListComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DomainListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { Domain, DomainListService } from './domainList.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-domain-list',
|
||||
templateUrl: './domainList.component.html',
|
||||
styleUrls: ['./domainList.component.scss'],
|
||||
providers: [DomainListService],
|
||||
})
|
||||
export class DomainListComponent {
|
||||
public static PATH = 'domain-list';
|
||||
|
||||
displayedColumns: string[] = [
|
||||
'domainName',
|
||||
'creationTime',
|
||||
'registrationExpirationTime',
|
||||
'statuses',
|
||||
];
|
||||
|
||||
dataSource: MatTableDataSource<Domain> = new MatTableDataSource();
|
||||
isLoading = true;
|
||||
|
||||
pageNumber?: number;
|
||||
resultsPerPage = 50;
|
||||
totalResults?: number;
|
||||
|
||||
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private domainListService: DomainListService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.reloadData();
|
||||
}
|
||||
|
||||
reloadData() {
|
||||
this.isLoading = true;
|
||||
this.domainListService
|
||||
.retrieveDomains(this.pageNumber, this.resultsPerPage, this.totalResults)
|
||||
.subscribe((domainListResult) => {
|
||||
this.dataSource.data = domainListResult.domains;
|
||||
this.totalResults = domainListResult.totalResults;
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/** TODO: the backend will need to accept a filter string. */
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
// const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.reloadData();
|
||||
}
|
||||
|
||||
onPageChange(event: PageEvent) {
|
||||
this.pageNumber = event.pageIndex;
|
||||
this.resultsPerPage = event.pageSize;
|
||||
this.reloadData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { tap } from 'rxjs';
|
||||
|
||||
export interface CreateAutoTimestamp {
|
||||
creationTime: string;
|
||||
}
|
||||
|
||||
export interface Domain {
|
||||
creationTime: CreateAutoTimestamp;
|
||||
currentSponsorRegistrarId: string;
|
||||
domainName: string;
|
||||
registrationExpirationTime: string;
|
||||
statuses: string[];
|
||||
}
|
||||
|
||||
export interface DomainListResult {
|
||||
checkpointTime: string;
|
||||
domains: Domain[];
|
||||
totalResults: number;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DomainListService {
|
||||
checkpointTime?: string;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
retrieveDomains(
|
||||
pageNumber?: number,
|
||||
resultsPerPage?: number,
|
||||
totalResults?: number
|
||||
) {
|
||||
return this.backendService
|
||||
.getDomains(
|
||||
this.registrarService.activeRegistrarId,
|
||||
this.checkpointTime,
|
||||
pageNumber,
|
||||
resultsPerPage,
|
||||
totalResults
|
||||
)
|
||||
.pipe(
|
||||
tap((domainListResult: DomainListResult) => {
|
||||
this.checkpointTime = domainListResult.checkpointTime;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,12 @@
|
||||
Create a Domain
|
||||
</button>
|
||||
<p class="secondary-text">Register a new domain name</p>
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="console-app__widget-link"
|
||||
(click)="openDomainsPage()"
|
||||
>
|
||||
View DUMs
|
||||
</button>
|
||||
<p class="secondary-text">
|
||||
|
||||
@@ -13,11 +13,17 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { DomainListComponent } from 'src/app/domains/domainList.component';
|
||||
|
||||
@Component({
|
||||
selector: '[app-domains-widget]',
|
||||
templateUrl: './domains-widget.component.html',
|
||||
})
|
||||
export class DomainsWidgetComponent {
|
||||
constructor() {}
|
||||
constructor(private router: Router) {}
|
||||
|
||||
openDomainsPage() {
|
||||
this.router.navigate([DomainListComponent.PATH]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Contact } from '../../settings/contact/contact.service';
|
||||
import { Registrar } from '../../registrar/registrar.service';
|
||||
import { UserData } from './userData.service';
|
||||
import { WhoisRegistrarFields } from 'src/app/settings/whois/whois.service';
|
||||
import { DomainListResult } from 'src/app/domains/domainList.service';
|
||||
|
||||
@Injectable()
|
||||
export class BackendService {
|
||||
@@ -63,6 +64,31 @@ export class BackendService {
|
||||
);
|
||||
}
|
||||
|
||||
getDomains(
|
||||
registrarId: string,
|
||||
checkpointTime?: string,
|
||||
pageNumber?: number,
|
||||
resultsPerPage?: number,
|
||||
totalResults?: number
|
||||
): Observable<DomainListResult> {
|
||||
var url = `/console-api/domain-list?registrarId=${registrarId}`;
|
||||
if (checkpointTime) {
|
||||
url += `&checkpointTime=${checkpointTime}`;
|
||||
}
|
||||
if (pageNumber) {
|
||||
url += `&pageNumber=${pageNumber}`;
|
||||
}
|
||||
if (resultsPerPage) {
|
||||
url += `&resultsPerPage=${resultsPerPage}`;
|
||||
}
|
||||
if (totalResults) {
|
||||
url += `&totalResults=${totalResults}`;
|
||||
}
|
||||
return this.http
|
||||
.get<DomainListResult>(url)
|
||||
.pipe(catchError((err) => this.errorCatcher<DomainListResult>(err)));
|
||||
}
|
||||
|
||||
getRegistrars(): Observable<Registrar[]> {
|
||||
return this.http
|
||||
.get<Registrar[]>('/console-api/registrars')
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
/** Identifiers of the BSA lists with blocking labels. */
|
||||
public enum BlockList {
|
||||
BLOCK,
|
||||
BLOCK_PLUS;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
/** The processing stages of a download. */
|
||||
public enum DownloadStage {
|
||||
/** Downloads BSA block list files. */
|
||||
DOWNLOAD,
|
||||
/** Generates block list diffs with the previous download. */
|
||||
MAKE_DIFF,
|
||||
/** Applies the label diffs to the database tables. */
|
||||
APPLY_DIFF,
|
||||
/**
|
||||
* Makes a REST API call to BSA endpoint, declaring that processing starts for new orders in the
|
||||
* diffs.
|
||||
*/
|
||||
START_UPLOADING,
|
||||
/** Makes a REST API call to BSA endpoint, sending the domains that cannot be blocked. */
|
||||
UPLOAD_DOMAINS_IN_USE,
|
||||
/** Makes a REST API call to BSA endpoint, declaring the completion of order processing. */
|
||||
FINISH_UPLOADING,
|
||||
/** The terminal stage after processing succeeds. */
|
||||
DONE,
|
||||
/**
|
||||
* The terminal stage indicating that the downloads are discarded because their checksums are the
|
||||
* same as that of the previous download.
|
||||
*/
|
||||
NOP,
|
||||
/**
|
||||
* The terminal stage indicating that the downloads are not processed because their BSA-generated
|
||||
* checksums do not match those calculated by us.
|
||||
*/
|
||||
CHECKSUMS_NOT_MATCH;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Action(
|
||||
service = Service.BSA,
|
||||
path = PlaceholderAction.PATH,
|
||||
method = Action.Method.GET,
|
||||
auth = Auth.AUTH_API_ADMIN)
|
||||
public class PlaceholderAction implements Runnable {
|
||||
private final Response response;
|
||||
|
||||
static final String PATH = "/_dr/task/bsaDownload";
|
||||
|
||||
@Inject
|
||||
public PlaceholderAction(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setStatus(SC_OK);
|
||||
response.setPayload("Hello World");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import google.registry.bsa.persistence.BsaDomainInUse.BsaDomainInUseId;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
|
||||
/** A domain matching a BSA label but is in use (registered or reserved), so cannot be blocked. */
|
||||
@Entity
|
||||
@IdClass(BsaDomainInUseId.class)
|
||||
public class BsaDomainInUse {
|
||||
@Id String label;
|
||||
@Id String tld;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
Reason reason;
|
||||
|
||||
/**
|
||||
* Creation time of this record, which is the most recent time when the domain was detected to be
|
||||
* in use wrt BSA. It may be during the processing of a download, or during some other job that
|
||||
* refreshes the state.
|
||||
*
|
||||
* <p>This field is for information only.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Column(nullable = false)
|
||||
CreateAutoTimestamp createTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
// For Hibernate
|
||||
BsaDomainInUse() {}
|
||||
|
||||
public BsaDomainInUse(String label, String tld, Reason reason) {
|
||||
this.label = label;
|
||||
this.tld = tld;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaDomainInUse)) {
|
||||
return false;
|
||||
}
|
||||
BsaDomainInUse that = (BsaDomainInUse) o;
|
||||
return Objects.equal(label, that.label)
|
||||
&& Objects.equal(tld, that.tld)
|
||||
&& reason == that.reason
|
||||
&& Objects.equal(createTime, that.createTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(label, tld, reason, createTime);
|
||||
}
|
||||
|
||||
enum Reason {
|
||||
REGISTERED,
|
||||
RESERVED;
|
||||
}
|
||||
|
||||
static class BsaDomainInUseId implements Serializable {
|
||||
|
||||
private String label;
|
||||
private String tld;
|
||||
|
||||
// For Hibernate
|
||||
BsaDomainInUseId() {}
|
||||
|
||||
BsaDomainInUseId(String label, String tld) {
|
||||
this.label = label;
|
||||
this.tld = tld;
|
||||
}
|
||||
}
|
||||
|
||||
static VKey<BsaDomainInUse> vKey(String label, String tld) {
|
||||
return VKey.create(BsaDomainInUse.class, new BsaDomainInUseId(label, tld));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static google.registry.bsa.DownloadStage.DOWNLOAD;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.bsa.BlockList;
|
||||
import google.registry.bsa.DownloadStage;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Records of ongoing and completed download jobs. */
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "creationTime")})
|
||||
public class BsaDownload {
|
||||
|
||||
private static final Joiner CSV_JOINER = Joiner.on(',');
|
||||
private static final Splitter CSV_SPLITTER = Splitter.on(',');
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long jobId;
|
||||
|
||||
@Column(nullable = false)
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
@Column(nullable = false)
|
||||
UpdateAutoTimestamp updateTime = UpdateAutoTimestamp.create(null);
|
||||
|
||||
@Column(nullable = false)
|
||||
String blockListChecksums = "";
|
||||
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
DownloadStage stage = DOWNLOAD;
|
||||
|
||||
BsaDownload() {}
|
||||
|
||||
long getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
DateTime getCreationTime() {
|
||||
return creationTime.getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the starting time of this job as a string, which can be used as folder name on GCS when
|
||||
* storing download data.
|
||||
*/
|
||||
public String getJobName() {
|
||||
return getCreationTime().toString();
|
||||
}
|
||||
|
||||
public DownloadStage getStage() {
|
||||
return this.stage;
|
||||
}
|
||||
|
||||
BsaDownload setStage(DownloadStage stage) {
|
||||
this.stage = stage;
|
||||
return this;
|
||||
}
|
||||
|
||||
BsaDownload setChecksums(ImmutableMap<BlockList, String> checksums) {
|
||||
blockListChecksums =
|
||||
CSV_JOINER.withKeyValueSeparator("=").join(ImmutableSortedMap.copyOf(checksums));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImmutableMap<BlockList, String> getChecksums() {
|
||||
if (blockListChecksums.isEmpty()) {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
return CSV_SPLITTER.withKeyValueSeparator('=').split(blockListChecksums).entrySet().stream()
|
||||
.collect(
|
||||
toImmutableMap(entry -> BlockList.valueOf(entry.getKey()), entry -> entry.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaDownload)) {
|
||||
return false;
|
||||
}
|
||||
BsaDownload that = (BsaDownload) o;
|
||||
return Objects.equal(creationTime, that.creationTime)
|
||||
&& Objects.equal(updateTime, that.updateTime)
|
||||
&& Objects.equal(blockListChecksums, that.blockListChecksums)
|
||||
&& stage == that.stage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(creationTime, updateTime, blockListChecksums, stage);
|
||||
}
|
||||
|
||||
static VKey<BsaDownload> vKey(long jobId) {
|
||||
return VKey.create(BsaDownload.class, Long.valueOf(jobId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Specifies a second-level TLD name that should be blocked from registration in all TLDs except by
|
||||
* the label's owner.
|
||||
*
|
||||
* <p>The label is valid (wrt IDN) in at least one TLD.
|
||||
*/
|
||||
@Entity
|
||||
public final class BsaLabel {
|
||||
|
||||
@Id String label;
|
||||
|
||||
/**
|
||||
* Creation time of this label. This field is for human use, and should give the name of the GCS
|
||||
* folder that contains the downloaded BSA data.
|
||||
*
|
||||
* <p>See {@link BsaDownload#getCreationTime} and {@link BsaDownload#getJobName} for more
|
||||
* information.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Column(nullable = false)
|
||||
DateTime creationTime;
|
||||
|
||||
// For Hibernate.
|
||||
BsaLabel() {}
|
||||
|
||||
BsaLabel(String label, DateTime creationTime) {
|
||||
this.label = label;
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
|
||||
/** Returns the label to be blocked. */
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BsaLabel)) {
|
||||
return false;
|
||||
}
|
||||
BsaLabel label1 = (BsaLabel) o;
|
||||
return Objects.equal(label, label1.label) && Objects.equal(creationTime, label1.creationTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(label, creationTime);
|
||||
}
|
||||
|
||||
static VKey<BsaLabel> vKey(String label) {
|
||||
return VKey.create(BsaLabel.class, label);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.bsa.BlockList;
|
||||
import google.registry.bsa.DownloadStage;
|
||||
import java.util.Optional;
|
||||
|
||||
/** Information needed when handling a download from BSA. */
|
||||
@AutoValue
|
||||
public abstract class DownloadSchedule {
|
||||
|
||||
abstract long jobId();
|
||||
|
||||
public abstract String jobName();
|
||||
|
||||
public abstract DownloadStage stage();
|
||||
|
||||
/** The most recent job that ended in the {@code DONE} stage. */
|
||||
public abstract Optional<CompletedJob> latestCompleted();
|
||||
|
||||
/**
|
||||
* Returns true if download should be processed even if the checksums show that it has not changed
|
||||
* from the previous one.
|
||||
*/
|
||||
abstract boolean alwaysDownload();
|
||||
|
||||
static DownloadSchedule of(BsaDownload currentJob) {
|
||||
return new AutoValue_DownloadSchedule(
|
||||
currentJob.getJobId(),
|
||||
currentJob.getJobName(),
|
||||
currentJob.getStage(),
|
||||
Optional.empty(),
|
||||
/* alwaysDownload= */ true);
|
||||
}
|
||||
|
||||
static DownloadSchedule of(
|
||||
BsaDownload currentJob, CompletedJob latestCompleted, boolean alwaysDownload) {
|
||||
return new AutoValue_DownloadSchedule(
|
||||
currentJob.getJobId(),
|
||||
currentJob.getJobName(),
|
||||
currentJob.getStage(),
|
||||
Optional.of(latestCompleted),
|
||||
/* alwaysDownload= */ alwaysDownload);
|
||||
}
|
||||
|
||||
/** Information about a completed BSA download job. */
|
||||
@AutoValue
|
||||
public abstract static class CompletedJob {
|
||||
public abstract String jobName();
|
||||
|
||||
public abstract ImmutableMap<BlockList, String> checksums();
|
||||
|
||||
static CompletedJob of(BsaDownload completedJob) {
|
||||
return new AutoValue_DownloadSchedule_CompletedJob(
|
||||
completedJob.getJobName(), completedJob.getChecksums());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.bsa.DownloadStage.CHECKSUMS_NOT_MATCH;
|
||||
import static google.registry.bsa.DownloadStage.DONE;
|
||||
import static google.registry.bsa.DownloadStage.NOP;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.Duration.standardSeconds;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.bsa.persistence.DownloadSchedule.CompletedJob;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Assigns work for each cron invocation of the BSA Download job.
|
||||
*
|
||||
* <p>The download job is invoked at a divisible fraction of the desired data freshness to
|
||||
* accommodate potential retries. E.g., for 30-minute data freshness with up to two retries on
|
||||
* error, the cron schedule for the job should be set to 10 minutes.
|
||||
*
|
||||
* <p>The processing of each BSA download progresses through multiple stages as described in {@code
|
||||
* DownloadStage} until it reaches one of the terminal stages. Each stage is check-pointed on
|
||||
* completion, therefore if an invocation fails mid-process, the next invocation will skip the
|
||||
* completed stages. No new downloads will start as long as the most recent one is still being
|
||||
* processed.
|
||||
*
|
||||
* <p>When a new download is scheduled, the block list checksums from the most recent completed job
|
||||
* is included. If the new checksums match the previous ones, the download may be skipped and the
|
||||
* job should terminate in the {@code NOP} stage. However, if the checksums have stayed unchanged
|
||||
* for longer than the user-provided {@code maxNopInterval}, the download will be processed.
|
||||
*
|
||||
* <p>The BSA downloads contains server-provided checksums. If they do not match the checksums
|
||||
* generated on Nomulus' side, the download is skipped and the job should terminate in the {@code
|
||||
* CHECKSUMS_NOT_MATCH} stage.
|
||||
*/
|
||||
public final class DownloadScheduler {
|
||||
|
||||
/** Allows a new download to proceed if the cron job fires a little early due to NTP drift. */
|
||||
private static final Duration CRON_JITTER = standardSeconds(5);
|
||||
|
||||
private final Duration downloadInterval;
|
||||
private final Duration maxNopInterval;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
DownloadScheduler(Duration downloadInterval, Duration maxNopInterval, Clock clock) {
|
||||
this.downloadInterval = downloadInterval;
|
||||
this.maxNopInterval = maxNopInterval;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DownloadSchedule} instance that describes the work to be performed by an
|
||||
* invocation of the download action, if applicable; or {@link Optional#empty} when there is
|
||||
* nothing to do.
|
||||
*/
|
||||
public Optional<DownloadSchedule> schedule() {
|
||||
return tm().transact(
|
||||
() -> {
|
||||
ImmutableList<BsaDownload> recentJobs = loadRecentProcessedJobs();
|
||||
if (recentJobs.isEmpty()) {
|
||||
// No jobs initiated ever.
|
||||
return Optional.of(scheduleNewJob(Optional.empty()));
|
||||
}
|
||||
BsaDownload mostRecent = recentJobs.get(0);
|
||||
if (mostRecent.getStage().equals(DONE)) {
|
||||
return isTimeAgain(mostRecent, downloadInterval)
|
||||
? Optional.of(scheduleNewJob(Optional.of(mostRecent)))
|
||||
: Optional.empty();
|
||||
} else if (recentJobs.size() == 1) {
|
||||
// First job ever, still in progress
|
||||
return Optional.of(DownloadSchedule.of(recentJobs.get(0)));
|
||||
} else {
|
||||
// Job in progress, with completed previous jobs.
|
||||
BsaDownload prev = recentJobs.get(1);
|
||||
verify(prev.getStage().equals(DONE), "Unexpectedly found two ongoing jobs.");
|
||||
return Optional.of(
|
||||
DownloadSchedule.of(
|
||||
mostRecent,
|
||||
CompletedJob.of(prev),
|
||||
isTimeAgain(mostRecent, maxNopInterval)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isTimeAgain(BsaDownload mostRecent, Duration interval) {
|
||||
return mostRecent.getCreationTime().plus(interval).minus(CRON_JITTER).isBefore(clock.nowUtc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new {@link BsaDownload} to the database and returns a {@link DownloadSchedule} for it.
|
||||
*/
|
||||
private DownloadSchedule scheduleNewJob(Optional<BsaDownload> prevJob) {
|
||||
BsaDownload job = new BsaDownload();
|
||||
tm().insert(job);
|
||||
return prevJob
|
||||
.map(
|
||||
prev ->
|
||||
DownloadSchedule.of(job, CompletedJob.of(prev), isTimeAgain(prev, maxNopInterval)))
|
||||
.orElseGet(() -> DownloadSchedule.of(job));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ImmutableList<BsaDownload> loadRecentProcessedJobs() {
|
||||
return ImmutableList.copyOf(
|
||||
tm().getEntityManager()
|
||||
.createQuery(
|
||||
"FROM BsaDownload WHERE stage NOT IN :nop_stages ORDER BY creationTime DESC")
|
||||
.setParameter("nop_stages", ImmutableList.of(CHECKSUMS_NOT_MATCH, NOP))
|
||||
.setMaxResults(2)
|
||||
.getResultList());
|
||||
}
|
||||
}
|
||||
@@ -1397,6 +1397,47 @@ public final class RegistryConfig {
|
||||
return config.bulkPricingPackageMonitoring.bulkPricingPackageDomainLimitUpgradeEmailBody;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaGcsBucket")
|
||||
public static String provideBsaGcsBucket(@Config("projectId") String projectId) {
|
||||
return projectId + "-bsa";
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaChecksumAlgorithm")
|
||||
public static String provideBsaChecksumAlgorithm(RegistryConfigSettings config) {
|
||||
return config.bsa.bsaChecksumAlgorithm;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaLockLeaseExpiry")
|
||||
public static Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
|
||||
return Duration.standardMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
|
||||
}
|
||||
|
||||
/** Returns the desired interval between successive BSA downloads. */
|
||||
@Provides
|
||||
@Config("bsaDownloadInterval")
|
||||
public static Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
|
||||
return Duration.standardMinutes(config.bsa.bsaDownloadIntervalMinutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum period when a BSA download can be skipped due to the checksum-based
|
||||
* equality check with the previous download.
|
||||
*/
|
||||
@Provides
|
||||
@Config("bsaMaxNopInterval")
|
||||
public static Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
|
||||
return Duration.standardHours(config.bsa.bsaMaxNopIntervalHours);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaLabelTxnBatchSize")
|
||||
public static int provideBsaLabelTxnBatchSize(RegistryConfigSettings config) {
|
||||
return config.bsa.bsaLabelTxnBatchSize;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaAuthUrl")
|
||||
public static String provideBsaAuthUrl(RegistryConfigSettings config) {
|
||||
@@ -1415,6 +1456,27 @@ public final class RegistryConfig {
|
||||
return ImmutableMap.copyOf(config.bsa.dataUrls);
|
||||
}
|
||||
|
||||
/** Provides the BSA Http endpoint for reporting order processing status. */
|
||||
@Provides
|
||||
@Config("bsaOrderStatusUrl")
|
||||
public static String provideBsaOrderStatusUrls(RegistryConfigSettings config) {
|
||||
return config.bsa.orderStatusUrl;
|
||||
}
|
||||
|
||||
/** Provides the BSA Http endpoint for reporting new unblockable domains. */
|
||||
@Provides
|
||||
@Config("bsaAddUnblockableDomainsUrl")
|
||||
public static String provideBsaAddUnblockableDomainsUrls(RegistryConfigSettings config) {
|
||||
return String.format("%s?%s", config.bsa.unblockableDomainsUrl, "action=add");
|
||||
}
|
||||
|
||||
/** Provides the BSA Http endpoint for reporting domains that have become blockable. */
|
||||
@Provides
|
||||
@Config("bsaRemoveUnblockableDomainsUrl")
|
||||
public static String provideBsaRemoveUnblockableDomainsUrls(RegistryConfigSettings config) {
|
||||
return String.format("%s?%s", config.bsa.unblockableDomainsUrl, "action=remove");
|
||||
}
|
||||
|
||||
private static String formatComments(String text) {
|
||||
return Splitter.on('\n').omitEmptyStrings().trimResults().splitToList(text).stream()
|
||||
.map(s -> "# " + s)
|
||||
@@ -1458,6 +1520,15 @@ public final class RegistryConfig {
|
||||
return makeUrl(CONFIG_SETTINGS.get().gcpProject.backendServiceUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address of the Nomulus app bsa HTTP server.
|
||||
*
|
||||
* <p>This is used by the {@code nomulus} tool to connect to the App Engine remote API.
|
||||
*/
|
||||
public static URL getBsaServer() {
|
||||
return makeUrl(CONFIG_SETTINGS.get().gcpProject.bsaServiceUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address of the Nomulus app tools HTTP server.
|
||||
*
|
||||
|
||||
@@ -53,6 +53,7 @@ public class RegistryConfigSettings {
|
||||
public boolean isLocal;
|
||||
public String defaultServiceUrl;
|
||||
public String backendServiceUrl;
|
||||
public String bsaServiceUrl;
|
||||
public String toolsServiceUrl;
|
||||
public String pubapiServiceUrl;
|
||||
}
|
||||
@@ -266,8 +267,15 @@ public class RegistryConfigSettings {
|
||||
|
||||
/** Configurations for integration with Brand Safety Alliance (BSA) API. */
|
||||
public static class Bsa {
|
||||
public String bsaChecksumAlgorithm;
|
||||
public int bsaLockLeaseExpiryMinutes;
|
||||
public int bsaDownloadIntervalMinutes;
|
||||
public int bsaMaxNopIntervalHours;
|
||||
public int bsaLabelTxnBatchSize;
|
||||
public String authUrl;
|
||||
public int authTokenExpirySeconds;
|
||||
public Map<String, String> dataUrls;
|
||||
public String orderStatusUrl;
|
||||
public String unblockableDomainsUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ gcpProject:
|
||||
# URLs of the services for the project.
|
||||
defaultServiceUrl: https://default.example.com
|
||||
backendServiceUrl: https://backend.example.com
|
||||
bsaServiceUrl: https://bsa.example.com
|
||||
toolsServiceUrl: https://tools.example.com
|
||||
pubapiServiceUrl: https://pubapi.example.com
|
||||
|
||||
|
||||
gSuite:
|
||||
# Publicly accessible domain name of the running G Suite instance.
|
||||
domainName: domain-registry.example
|
||||
@@ -615,3 +617,7 @@ bsa:
|
||||
dataUrls:
|
||||
"BLOCK": "https://"
|
||||
"BLOCK_PLUS": "https://"
|
||||
# Http endpoint for reporting order processing status
|
||||
orderStatusUrl: "https://"
|
||||
# Http endpoint for reporting changes in the set of unblockable domains.
|
||||
unblockableDomainsUrl: "https://"
|
||||
|
||||
-7
@@ -18,13 +18,6 @@
|
||||
value="alpha"/>
|
||||
</system-properties>
|
||||
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-alpha/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1m"/>
|
||||
</static-files>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java17</runtime>
|
||||
<service>bsa</service>
|
||||
<app-engine-apis>true</app-engine-apis>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>100</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="alpha"/>
|
||||
</system-properties>
|
||||
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-alpha/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1m"/>
|
||||
</static-files>
|
||||
</appengine-web-app>
|
||||
@@ -31,6 +31,12 @@ encoding="UTF-8"?>
|
||||
<context-root>backend</context-root>
|
||||
</web>
|
||||
</module>
|
||||
<module>
|
||||
<web>
|
||||
<web-uri>bsa</web-uri>
|
||||
<context-root>bsa</context-root>
|
||||
</web>
|
||||
</module>
|
||||
<module>
|
||||
<web>
|
||||
<web-uri>tools</web-uri>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# A default java.util.logging configuration.
|
||||
# (All App Engine logging is through java.util.logging by default).
|
||||
#
|
||||
# To use this configuration, copy it into your application's WEB-INF
|
||||
# folder and add the following to your appengine-web.xml:
|
||||
#
|
||||
# <system-properties>
|
||||
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
|
||||
# </system-properties>
|
||||
#
|
||||
|
||||
# Set the default logging level for all loggers to INFO.
|
||||
.level = INFO
|
||||
|
||||
# Turn off logging in Hibernate classes for misleading ERROR-level logs
|
||||
org.hibernate.engine.jdbc.batch.internal.BatchingBatch.level=OFF
|
||||
org.hibernate.engine.jdbc.spi.SqlExceptionHelper.level=OFF
|
||||
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected backends actions -->
|
||||
<servlet>
|
||||
<display-name>BsaServlet</display-name>
|
||||
<servlet-name>bsa-servlet</servlet-name>
|
||||
<servlet-class>google.registry.module.bsa.BsaServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- Test action -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>bsa-servlet</servlet-name>
|
||||
<url-pattern>/_dr/task/bsaDownload</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security config -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Internal</web-resource-name>
|
||||
<description>
|
||||
Admin-only internal section. Requests for paths covered by the URL patterns below will be
|
||||
checked for a logged-in user account that's allowed to access the AppEngine admin console
|
||||
(NOTE: this includes Editor/Viewer permissions in addition to Owner and the new IAM
|
||||
App Engine Admin role. See https://cloud.google.com/appengine/docs/java/access-control
|
||||
specifically the "Access handlers that have a login:admin restriction" line.)
|
||||
|
||||
TODO(b/28219927): lift some of these restrictions so that we can allow OAuth authentication
|
||||
for endpoints that need to be accessed by open-source automated processes.
|
||||
</description>
|
||||
|
||||
<!-- Internal AppEngine endpoints. The '_ah' is short for app hosting. -->
|
||||
<url-pattern>/_ah/*</url-pattern>
|
||||
|
||||
<!-- Registrar console (should not be available on non-default module). -->
|
||||
<url-pattern>/registrar*</url-pattern>
|
||||
|
||||
<!-- Verbatim JavaScript sources (only visible to admins for debugging). -->
|
||||
<url-pattern>/assets/sources/*</url-pattern>
|
||||
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>admin</role-name>
|
||||
</auth-constraint>
|
||||
|
||||
<!-- Repeated here since catch-all rule below is not inherited. -->
|
||||
<user-data-constraint>
|
||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||
</user-data-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<!-- Require TLS on all requests. -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Secure</web-resource-name>
|
||||
<description>
|
||||
Require encryption for all paths. http URLs will be redirected to https.
|
||||
</description>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<user-data-constraint>
|
||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||
</user-data-constraint>
|
||||
</security-constraint>
|
||||
</web-app>
|
||||
-6
@@ -18,12 +18,6 @@
|
||||
value="crash"/>
|
||||
</system-properties>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-crash/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1m"/>
|
||||
</static-files>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java17</runtime>
|
||||
<service>bsa</service>
|
||||
<app-engine-apis>true</app-engine-apis>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>10</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="crash"/>
|
||||
</system-properties>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-crash/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1m"/>
|
||||
</static-files>
|
||||
</appengine-web-app>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java17</runtime>
|
||||
<service>bsa</service>
|
||||
<app-engine-apis>true</app-engine-apis>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>10</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="local"/>
|
||||
<property name="appengine.generated.dir"
|
||||
value="/tmp/domain-registry-appengine-generated/local/"/>
|
||||
</system-properties>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html">
|
||||
<http-header name="Cache-Control" value="max-age=0,must-revalidate" />
|
||||
</include>
|
||||
</static-files>
|
||||
</appengine-web-app>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java8</runtime>
|
||||
<service>bsa</service>
|
||||
<!--app-engine-apis>true</app-engine-apis-->
|
||||
<threadsafe>true</threadsafe>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4_1G</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>100</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="production"/>
|
||||
</system-properties>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1d"/>
|
||||
</static-files>
|
||||
|
||||
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->
|
||||
<static-error-handlers>
|
||||
<handler file="error.html"/>
|
||||
</static-error-handlers>
|
||||
</appengine-web-app>
|
||||
@@ -22,12 +22,6 @@
|
||||
<include path="/*.html" expiration="1h"/>
|
||||
</static-files>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-qa/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->
|
||||
<static-error-handlers>
|
||||
<handler file="error.html"/>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java17</runtime>
|
||||
<service>bsa</service>
|
||||
<app-engine-apis>true</app-engine-apis>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>10</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="qa"/>
|
||||
</system-properties>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1h"/>
|
||||
</static-files>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-qa/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->
|
||||
<static-error-handlers>
|
||||
<handler file="error.html"/>
|
||||
</static-error-handlers>
|
||||
</appengine-web-app>
|
||||
-6
@@ -23,12 +23,6 @@
|
||||
<include path="/*.html" expiration="1d"/>
|
||||
</static-files>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-sandbox/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->
|
||||
<static-error-handlers>
|
||||
<handler file="error.html"/>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||
|
||||
<runtime>java8</runtime>
|
||||
<service>bsa</service>
|
||||
<!--app-engine-apis>true</app-engine-apis-->
|
||||
<threadsafe>true</threadsafe>
|
||||
<sessions-enabled>true</sessions-enabled>
|
||||
<instance-class>B4</instance-class>
|
||||
<basic-scaling>
|
||||
<max-instances>100</max-instances>
|
||||
<idle-timeout>10m</idle-timeout>
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
value="sandbox"/>
|
||||
</system-properties>
|
||||
|
||||
<static-files>
|
||||
<include path="/*.html" expiration="1d"/>
|
||||
</static-files>
|
||||
|
||||
<!-- Enable external traffic to go through VPC, required for static ip -->
|
||||
<vpc-access-connector>
|
||||
<name>projects/domain-registry-sandbox/locations/us-central1/connectors/appengine-connector</name>
|
||||
<egress-setting>all-traffic</egress-setting>
|
||||
</vpc-access-connector>
|
||||
|
||||
<!-- Prevent uncaught servlet errors from leaking a stack trace. -->
|
||||
<static-error-handlers>
|
||||
<handler file="error.html"/>
|
||||
</static-error-handlers>
|
||||
</appengine-web-app>
|
||||
@@ -75,14 +75,6 @@ public class EppRequestHandler {
|
||||
&& eppOutput.getResponse().getResult().getCode() == SUCCESS_AND_CLOSE) {
|
||||
response.setHeader(ProxyHttpHeaders.EPP_SESSION, "close");
|
||||
}
|
||||
// If a login request returns a success, a logged-in header is added to the response to inform
|
||||
// the proxy that it is no longer necessary to send the full client certificate to the backend
|
||||
// for this connection.
|
||||
if (eppOutput.isResponse()
|
||||
&& eppOutput.getResponse().isLoginResponse()
|
||||
&& eppOutput.isSuccess()) {
|
||||
response.setHeader(ProxyHttpHeaders.LOGGED_IN, "true");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.atWarning().withCause(e).log("handleEppCommand general exception.");
|
||||
response.setStatus(SC_BAD_REQUEST);
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.common.net.InetAddresses;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.flows.certs.CertificateChecker.InsecureCertificateException;
|
||||
@@ -66,11 +67,11 @@ public class TlsCredentials implements TransportCredentials {
|
||||
public TlsCredentials(
|
||||
@Config("requireSslCertificates") boolean requireSslCertificates,
|
||||
@Header(ProxyHttpHeaders.CERTIFICATE_HASH) Optional<String> clientCertificateHash,
|
||||
@Header(ProxyHttpHeaders.IP_ADDRESS) Optional<String> clientAddress,
|
||||
Optional<InetAddress> clientInetAddr,
|
||||
CertificateChecker certificateChecker) {
|
||||
this.requireSslCertificates = requireSslCertificates;
|
||||
this.clientCertificateHash = clientCertificateHash;
|
||||
this.clientInetAddr = clientAddress.map(TlsCredentials::parseInetAddress);
|
||||
this.clientInetAddr = clientInetAddr;
|
||||
this.certificateChecker = certificateChecker;
|
||||
}
|
||||
|
||||
@@ -104,18 +105,25 @@ public class TlsCredentials implements TransportCredentials {
|
||||
}
|
||||
// In the rare unexpected case that the client inet address wasn't passed along at all, then
|
||||
// by default deny access.
|
||||
if (clientInetAddr.isPresent()) {
|
||||
for (CidrAddressBlock cidrAddressBlock : ipAddressAllowList) {
|
||||
if (cidrAddressBlock.contains(clientInetAddr.get())) {
|
||||
// IP address is in allow list; return early.
|
||||
return;
|
||||
}
|
||||
if (!clientInetAddr.isPresent()) {
|
||||
logger.atWarning().log(
|
||||
"Authentication error: Missing IP address for registrar %s.", registrar.getRegistrarId());
|
||||
throw new BadRegistrarIpAddressException(clientInetAddr);
|
||||
}
|
||||
for (CidrAddressBlock cidrAddressBlock : ipAddressAllowList) {
|
||||
if (cidrAddressBlock.contains(clientInetAddr.get())) {
|
||||
// IP address is in allow list; return early.
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger.atInfo().log(
|
||||
logger.atWarning().log(
|
||||
"Authentication error: IP address %s is not allow-listed for registrar %s; allow list is:"
|
||||
+ " %s",
|
||||
clientInetAddr, registrar.getRegistrarId(), ipAddressAllowList);
|
||||
clientInetAddr,
|
||||
registrar.getRegistrarId(),
|
||||
RegistryEnvironment.get() == RegistryEnvironment.PRODUCTION
|
||||
? "redacted in production"
|
||||
: ipAddressAllowList);
|
||||
throw new BadRegistrarIpAddressException(clientInetAddr);
|
||||
}
|
||||
|
||||
@@ -232,7 +240,7 @@ public class TlsCredentials implements TransportCredentials {
|
||||
? String.format(
|
||||
"Registrar IP address %s is not in stored allow list",
|
||||
clientInetAddr.get().getHostAddress())
|
||||
: "Registrar IP address is not in stored allow list");
|
||||
: "Registrar IP address is missing");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,9 +257,14 @@ public class TlsCredentials implements TransportCredentials {
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Header(ProxyHttpHeaders.IP_ADDRESS)
|
||||
static Optional<String> provideIpAddress(HttpServletRequest req) {
|
||||
return extractOptionalHeader(req, ProxyHttpHeaders.IP_ADDRESS);
|
||||
static Optional<InetAddress> provideIpAddress(HttpServletRequest req) {
|
||||
Optional<String> clientAddress = extractOptionalHeader(req, ProxyHttpHeaders.IP_ADDRESS);
|
||||
Optional<String> fallbackClientAddress =
|
||||
extractOptionalHeader(req, ProxyHttpHeaders.IP_ADDRESS);
|
||||
Optional<InetAddress> clientInetAddr = clientAddress.map(TlsCredentials::parseInetAddress);
|
||||
return clientInetAddr.isPresent()
|
||||
? clientInetAddr
|
||||
: fallbackClientAddress.map(TlsCredentials::parseInetAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ public final class GmailClient {
|
||||
BodyPart attachmentPart = new MimeBodyPart();
|
||||
attachmentPart.setContent(attachment.content(), attachment.contentType().toString());
|
||||
attachmentPart.setFileName(attachment.filename());
|
||||
attachmentPart.setDisposition(MimeBodyPart.ATTACHMENT);
|
||||
multipart.addBodyPart(attachmentPart);
|
||||
}
|
||||
msg.addRecipients(RecipientType.BCC, toArray(emailMessage.bccs(), Address.class));
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.module.bsa;
|
||||
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import dagger.Component;
|
||||
import dagger.Lazy;
|
||||
import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.module.bsa.BsaRequestComponent.BsaRequestComponentModule;
|
||||
import google.registry.monitoring.whitebox.StackdriverModule;
|
||||
import google.registry.request.Modules.GsonModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
@Component(
|
||||
modules = {
|
||||
AuthModule.class,
|
||||
UtilsModule.class,
|
||||
UserServiceModule.class,
|
||||
GsonModule.class,
|
||||
ConfigModule.class,
|
||||
StackdriverModule.class,
|
||||
CredentialModule.class,
|
||||
BsaRequestComponentModule.class
|
||||
})
|
||||
interface BsaComponent {
|
||||
BsaRequestHandler requestHandler();
|
||||
|
||||
Lazy<MetricReporter> metricReporter();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.module.bsa;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Subcomponent;
|
||||
import google.registry.bsa.PlaceholderAction;
|
||||
import google.registry.request.RequestComponentBuilder;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.RequestScope;
|
||||
|
||||
@RequestScope
|
||||
@Subcomponent(
|
||||
modules = {
|
||||
RequestModule.class,
|
||||
})
|
||||
interface BsaRequestComponent {
|
||||
|
||||
PlaceholderAction bsaAction();
|
||||
|
||||
@Subcomponent.Builder
|
||||
abstract class Builder implements RequestComponentBuilder<BsaRequestComponent> {
|
||||
|
||||
@Override
|
||||
public abstract Builder requestModule(RequestModule requestModule);
|
||||
|
||||
@Override
|
||||
public abstract BsaRequestComponent build();
|
||||
}
|
||||
|
||||
@Module(subcomponents = BsaRequestComponent.class)
|
||||
class BsaRequestComponentModule {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.module.bsa;
|
||||
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
public class BsaRequestHandler extends RequestHandler<BsaRequestComponent> {
|
||||
@Inject
|
||||
public BsaRequestHandler(
|
||||
Provider<BsaRequestComponent.Builder> componentBuilderProvider,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
super(componentBuilderProvider, requestAuthenticator);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.module.bsa;
|
||||
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import dagger.Lazy;
|
||||
import google.registry.module.ServletBase;
|
||||
|
||||
public final class BsaServlet extends ServletBase {
|
||||
|
||||
private static final BsaComponent component = DaggerBsaComponent.create();
|
||||
private static final BsaRequestHandler requestHandler = component.requestHandler();
|
||||
private static final Lazy<MetricReporter> metricReporter = component.metricReporter();
|
||||
|
||||
public BsaServlet() {
|
||||
super(requestHandler, metricReporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
@javax.annotation.ParametersAreNonnullByDefault
|
||||
package google.registry.module.bsa;
|
||||
@@ -39,7 +39,7 @@ import javax.persistence.PersistenceException;
|
||||
* <p>See the {@code logging.properties} files in the {@code env} package for the specific Hibernate
|
||||
* classes that have logging suppressed.
|
||||
*/
|
||||
class DatabaseException extends PersistenceException {
|
||||
public class DatabaseException extends PersistenceException {
|
||||
|
||||
private transient String cachedMessage;
|
||||
|
||||
|
||||
@@ -30,11 +30,13 @@ public @interface Action {
|
||||
|
||||
/** App Engine services supported by the request processor. */
|
||||
enum Service {
|
||||
BSA("bsa"),
|
||||
DEFAULT("default"),
|
||||
TOOLS("tools"),
|
||||
BACKEND("backend"),
|
||||
PUBAPI("pubapi");
|
||||
|
||||
|
||||
private final String serviceId;
|
||||
|
||||
Service(String serviceId) {
|
||||
|
||||
@@ -170,6 +170,8 @@ public class ServiceConnection {
|
||||
return RegistryConfig.getToolsServer();
|
||||
case BACKEND:
|
||||
return RegistryConfig.getBackendServer();
|
||||
case BSA:
|
||||
return RegistryConfig.getBsaServer();
|
||||
case PUBAPI:
|
||||
return RegistryConfig.getPubapiServer();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.util.X509Utils.loadCertificate;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.flows.TlsCredentials;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -85,7 +86,7 @@ final class ValidateLoginCredentialsCommand implements Command {
|
||||
new TlsCredentials(
|
||||
true,
|
||||
Optional.ofNullable(clientCertificateHash),
|
||||
Optional.ofNullable(clientIpAddress),
|
||||
Optional.ofNullable(InetAddresses.forString(clientIpAddress)),
|
||||
certificateChecker)
|
||||
.validate(registrar, password);
|
||||
checkState(
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
|
||||
<mapping-file>META-INF/orm.xml</mapping-file>
|
||||
|
||||
<class>google.registry.bsa.persistence.BsaDownload</class>
|
||||
<class>google.registry.bsa.persistence.BsaLabel</class>
|
||||
<class>google.registry.bsa.persistence.BsaDomainInUse</class>
|
||||
<class>google.registry.model.billing.BillingCancellation</class>
|
||||
<class>google.registry.model.billing.BillingEvent</class>
|
||||
<class>google.registry.model.billing.BillingRecurrence</class>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.bsa.persistence.BsaDomainInUse.Reason;
|
||||
import google.registry.persistence.transaction.DatabaseException;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link BsaDomainInUse}. */
|
||||
public class BsaDomainInUseTest {
|
||||
|
||||
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
@Test
|
||||
void persist() {
|
||||
tm().transact(() -> tm().put(new BsaLabel("label", fakeClock.nowUtc())));
|
||||
tm().transact(() -> tm().put(new BsaDomainInUse("label", "tld", Reason.REGISTERED)));
|
||||
BsaDomainInUse persisted =
|
||||
tm().transact(() -> tm().loadByKey(BsaDomainInUse.vKey("label", "tld")));
|
||||
assertThat(persisted.label).isEqualTo("label");
|
||||
assertThat(persisted.tld).isEqualTo("tld");
|
||||
assertThat(persisted.reason).isEqualTo(Reason.REGISTERED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void cascadeDeletion() {
|
||||
tm().transact(() -> tm().put(new BsaLabel("label", fakeClock.nowUtc())));
|
||||
tm().transact(() -> tm().put(new BsaDomainInUse("label", "tld", Reason.REGISTERED)));
|
||||
assertThat(tm().transact(() -> tm().loadByKeyIfPresent(BsaDomainInUse.vKey("label", "tld"))))
|
||||
.isPresent();
|
||||
tm().transact(() -> tm().delete(BsaLabel.vKey("label")));
|
||||
assertThat(tm().transact(() -> tm().loadByKeyIfPresent(BsaDomainInUse.vKey("label", "tld"))))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void insertDomainWithoutLabel() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
DatabaseException.class,
|
||||
() ->
|
||||
tm().transact(
|
||||
() -> tm().put(new BsaDomainInUse("label", "tld", Reason.REGISTERED)))))
|
||||
.hasMessageThat()
|
||||
.contains("violates foreign key constraint");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.bsa.BlockList.BLOCK;
|
||||
import static google.registry.bsa.BlockList.BLOCK_PLUS;
|
||||
import static google.registry.bsa.DownloadStage.DOWNLOAD;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.bsa.BlockList;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit test for {@link BsaDownload}. */
|
||||
public class BsaDownloadTest {
|
||||
|
||||
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
@Test
|
||||
void saveJob() {
|
||||
BsaDownload persisted = tm().transact(() -> tm().getEntityManager().merge(new BsaDownload()));
|
||||
assertThat(persisted.jobId).isNotNull();
|
||||
assertThat(persisted.creationTime.getTimestamp()).isEqualTo(fakeClock.nowUtc());
|
||||
assertThat(persisted.stage).isEqualTo(DOWNLOAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadJobByKey() {
|
||||
BsaDownload persisted = tm().transact(() -> tm().getEntityManager().merge(new BsaDownload()));
|
||||
assertThat(tm().transact(() -> tm().loadByKey(BsaDownload.vKey(persisted.jobId))))
|
||||
.isEqualTo(persisted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void checksums() {
|
||||
BsaDownload job = new BsaDownload();
|
||||
assertThat(job.getChecksums()).isEmpty();
|
||||
ImmutableMap<BlockList, String> checksums = ImmutableMap.of(BLOCK, "a", BLOCK_PLUS, "b");
|
||||
job.setChecksums(checksums);
|
||||
assertThat(job.getChecksums()).isEqualTo(checksums);
|
||||
assertThat(job.blockListChecksums).isEqualTo("BLOCK=a,BLOCK_PLUS=b");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link BsaLabel}. */
|
||||
public class BsaLabelTest {
|
||||
|
||||
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
@Test
|
||||
void persist() {
|
||||
tm().transact(() -> tm().put(new BsaLabel("label", fakeClock.nowUtc())));
|
||||
BsaLabel persisted = tm().transact(() -> tm().loadByKey(BsaLabel.vKey("label")));
|
||||
assertThat(persisted.getLabel()).isEqualTo("label");
|
||||
assertThat(persisted.creationTime).isEqualTo(fakeClock.nowUtc());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.bsa.DownloadStage.CHECKSUMS_NOT_MATCH;
|
||||
import static google.registry.bsa.DownloadStage.DONE;
|
||||
import static google.registry.bsa.DownloadStage.DOWNLOAD;
|
||||
import static google.registry.bsa.DownloadStage.MAKE_DIFF;
|
||||
import static google.registry.bsa.DownloadStage.NOP;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
import static org.joda.time.Duration.standardMinutes;
|
||||
import static org.joda.time.Duration.standardSeconds;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.bsa.BlockList;
|
||||
import google.registry.bsa.DownloadStage;
|
||||
import google.registry.bsa.persistence.DownloadSchedule.CompletedJob;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DownloadScheduler} */
|
||||
public class DownloadSchedulerTest {
|
||||
|
||||
static final Duration DOWNLOAD_INTERVAL = standardMinutes(30);
|
||||
static final Duration MAX_NOP_INTERVAL = standardDays(1);
|
||||
|
||||
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
private DownloadScheduler scheduler;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
scheduler = new DownloadScheduler(DOWNLOAD_INTERVAL, MAX_NOP_INTERVAL, fakeClock);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void dbCheck() {
|
||||
ImmutableSet<DownloadStage> terminalStages = ImmutableSet.of(DONE, NOP, CHECKSUMS_NOT_MATCH);
|
||||
assertThat(
|
||||
tm().transact(
|
||||
() ->
|
||||
tm().getEntityManager()
|
||||
.createQuery("FROM BsaDownload", BsaDownload.class)
|
||||
.getResultStream()
|
||||
.filter(job -> !terminalStages.contains(job.getStage()))
|
||||
.count()))
|
||||
.isAtMost(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void firstJobEver() {
|
||||
Optional<DownloadSchedule> scheduleOptional = scheduler.schedule();
|
||||
assertThat(scheduleOptional).isPresent();
|
||||
DownloadSchedule schedule = scheduleOptional.get();
|
||||
assertThat(schedule.latestCompleted()).isEmpty();
|
||||
assertThat(schedule.jobName()).isEqualTo(fakeClock.nowUtc().toString());
|
||||
assertThat(schedule.stage()).isEqualTo(DownloadStage.DOWNLOAD);
|
||||
assertThat(schedule.alwaysDownload()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void oneInProgressJob() {
|
||||
BsaDownload inProgressJob = insertOneJobAndAdvanceClock(MAKE_DIFF);
|
||||
Optional<DownloadSchedule> scheduleOptional = scheduler.schedule();
|
||||
assertThat(scheduleOptional).isPresent();
|
||||
DownloadSchedule schedule = scheduleOptional.get();
|
||||
assertThat(schedule.jobId()).isEqualTo(inProgressJob.jobId);
|
||||
assertThat(schedule.jobName()).isEqualTo(inProgressJob.getJobName());
|
||||
assertThat(schedule.stage()).isEqualTo(MAKE_DIFF);
|
||||
assertThat(schedule.latestCompleted()).isEmpty();
|
||||
assertThat(schedule.alwaysDownload()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void oneInProgressJobOneCompletedJob() {
|
||||
BsaDownload completed = insertOneJobAndAdvanceClock(DONE);
|
||||
BsaDownload inProgressJob = insertOneJobAndAdvanceClock(MAKE_DIFF);
|
||||
Optional<DownloadSchedule> scheduleOptional = scheduler.schedule();
|
||||
assertThat(scheduleOptional).isPresent();
|
||||
DownloadSchedule schedule = scheduleOptional.get();
|
||||
assertThat(schedule.jobId()).isEqualTo(inProgressJob.jobId);
|
||||
assertThat(schedule.jobName()).isEqualTo(inProgressJob.getJobName());
|
||||
assertThat(schedule.stage()).isEqualTo(MAKE_DIFF);
|
||||
assertThat(schedule.alwaysDownload()).isFalse();
|
||||
assertThat(schedule.latestCompleted()).isPresent();
|
||||
CompletedJob lastCompleted = schedule.latestCompleted().get();
|
||||
assertThat(lastCompleted.jobName()).isEqualTo(completed.getJobName());
|
||||
assertThat(lastCompleted.checksums()).isEqualTo(completed.getChecksums());
|
||||
}
|
||||
|
||||
@Test
|
||||
void doneJob_noNewSchedule() {
|
||||
insertOneJobAndAdvanceClock(DONE);
|
||||
assertThat(scheduler.schedule()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doneJob_newSchedule() {
|
||||
BsaDownload completed = insertOneJobAndAdvanceClock(DONE);
|
||||
fakeClock.advanceBy(DOWNLOAD_INTERVAL);
|
||||
Optional<DownloadSchedule> scheduleOptional = scheduler.schedule();
|
||||
assertThat(scheduleOptional).isPresent();
|
||||
DownloadSchedule schedule = scheduleOptional.get();
|
||||
assertThat(schedule.stage()).isEqualTo(DOWNLOAD);
|
||||
assertThat(schedule.alwaysDownload()).isFalse();
|
||||
assertThat(schedule.latestCompleted()).isPresent();
|
||||
CompletedJob completedJob = schedule.latestCompleted().get();
|
||||
assertThat(completedJob.jobName()).isEqualTo(completed.getJobName());
|
||||
assertThat(completedJob.checksums()).isEqualTo(completedJob.checksums());
|
||||
}
|
||||
|
||||
@Test
|
||||
void doneJob_newSchedule_alwaysDownload() {
|
||||
insertOneJobAndAdvanceClock(DONE);
|
||||
fakeClock.advanceBy(MAX_NOP_INTERVAL);
|
||||
Optional<DownloadSchedule> scheduleOptional = scheduler.schedule();
|
||||
assertThat(scheduleOptional).isPresent();
|
||||
DownloadSchedule schedule = scheduleOptional.get();
|
||||
assertThat(schedule.alwaysDownload()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doneJob_cronEarlyWithJitter_newSchedule() {
|
||||
insertOneJobAndAdvanceClock(DONE);
|
||||
fakeClock.advanceBy(DOWNLOAD_INTERVAL.minus(standardSeconds(5)));
|
||||
assertThat(scheduler.schedule()).isPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doneJob_cronEarlyMoreThanJitter_newSchedule() {
|
||||
insertOneJobAndAdvanceClock(DONE);
|
||||
fakeClock.advanceBy(DOWNLOAD_INTERVAL.minus(standardSeconds(6)));
|
||||
assertThat(scheduler.schedule()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadRecentProcessedJobs_noneExists() {
|
||||
assertThat(tm().transact(() -> scheduler.loadRecentProcessedJobs())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadRecentProcessedJobs_nopJobsOnly() {
|
||||
insertOneJobAndAdvanceClock(DownloadStage.NOP);
|
||||
insertOneJobAndAdvanceClock(DownloadStage.CHECKSUMS_NOT_MATCH);
|
||||
assertThat(tm().transact(() -> scheduler.loadRecentProcessedJobs())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadRecentProcessedJobs_oneInProgressJob() {
|
||||
BsaDownload job = insertOneJobAndAdvanceClock(MAKE_DIFF);
|
||||
assertThat(tm().transact(() -> scheduler.loadRecentProcessedJobs())).containsExactly(job);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadRecentProcessedJobs_oneDoneJob() {
|
||||
BsaDownload job = insertOneJobAndAdvanceClock(DONE);
|
||||
assertThat(tm().transact(() -> scheduler.loadRecentProcessedJobs())).containsExactly(job);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadRecentProcessedJobs_multipleJobs() {
|
||||
insertOneJobAndAdvanceClock(DownloadStage.DONE);
|
||||
insertOneJobAndAdvanceClock(DownloadStage.DONE);
|
||||
BsaDownload completed = insertOneJobAndAdvanceClock(DownloadStage.DONE);
|
||||
insertOneJobAndAdvanceClock(DownloadStage.NOP);
|
||||
insertOneJobAndAdvanceClock(DownloadStage.CHECKSUMS_NOT_MATCH);
|
||||
BsaDownload inprogress = insertOneJobAndAdvanceClock(DownloadStage.APPLY_DIFF);
|
||||
assertThat(tm().transact(() -> scheduler.loadRecentProcessedJobs()))
|
||||
.containsExactly(inprogress, completed)
|
||||
.inOrder();
|
||||
}
|
||||
|
||||
private BsaDownload insertOneJobAndAdvanceClock(DownloadStage stage) {
|
||||
BsaDownload job = new BsaDownload();
|
||||
job.setStage(stage);
|
||||
job.setChecksums(ImmutableMap.of(BlockList.BLOCK, "1", BlockList.BLOCK_PLUS, "2"));
|
||||
tm().transact(() -> tm().insert(job));
|
||||
fakeClock.advanceOneMilli();
|
||||
return job;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import static google.registry.util.X509Utils.getCertificateHash;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
@@ -66,7 +67,7 @@ class EppLoginTlsTest extends EppTestCase {
|
||||
new TlsCredentials(
|
||||
true,
|
||||
Optional.ofNullable(clientCertificateHash),
|
||||
Optional.of("192.168.1.100:54321"),
|
||||
Optional.of(InetAddresses.forString("192.168.1.100")),
|
||||
certificateChecker));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ import google.registry.persistence.VKey;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeHttpSession;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.util.ProxyHttpHeaders;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -126,10 +125,6 @@ public class EppTestCase {
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Check that the logged-in header was added to the response
|
||||
assertThat(response.getHeaders())
|
||||
.isEqualTo(ImmutableMap.of(ProxyHttpHeaders.LOGGED_IN, "true"));
|
||||
|
||||
verifyAndReturnOutput(response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
|
||||
@@ -146,10 +141,6 @@ public class EppTestCase {
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Checks that the Logged-In header is not in the response. If testing the login command, use
|
||||
// assertLoginCommandAndResponse instead of this method.
|
||||
assertThat(response.getHeaders()).doesNotContainEntry(ProxyHttpHeaders.LOGGED_IN, "true");
|
||||
|
||||
return verifyAndReturnOutput(
|
||||
response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.google.common.testing.TestLogHandler;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -186,7 +187,10 @@ class FlowRunnerTest {
|
||||
void testRun_loggingStatement_tlsCredentials() throws Exception {
|
||||
flowRunner.credentials =
|
||||
new TlsCredentials(
|
||||
true, Optional.of("abc123def"), Optional.of("127.0.0.1"), certificateChecker);
|
||||
true,
|
||||
Optional.of("abc123def"),
|
||||
Optional.of(InetAddresses.forString("127.0.0.1")),
|
||||
certificateChecker);
|
||||
flowRunner.run(eppMetricBuilder);
|
||||
assertThat(Splitter.on("\n\t").split(findFirstLogMessageByPrefix(handler, "EPP Command\n\t")))
|
||||
.contains("TlsCredentials{clientCertificateHash=abc123def," + " clientAddress=/127.0.0.1}");
|
||||
|
||||
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.flows.TlsCredentials.BadRegistrarIpAddressException;
|
||||
import google.registry.flows.TlsCredentials.MissingRegistrarCertificateException;
|
||||
import google.registry.flows.TlsCredentials.RegistrarCertificateNotConfiguredException;
|
||||
@@ -71,7 +72,11 @@ final class TlsCredentialsTest {
|
||||
@Test
|
||||
void testClientCertificateAndHash_missing() {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(true, Optional.empty(), Optional.of("192.168.1.1"), certificateChecker);
|
||||
new TlsCredentials(
|
||||
true,
|
||||
Optional.empty(),
|
||||
Optional.of(InetAddresses.forString("192.168.1.1")),
|
||||
certificateChecker);
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
@@ -83,10 +88,13 @@ final class TlsCredentialsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_missingIpAddress_doesntAllowAccess() {
|
||||
void test_wrongIpAddress_doesntAllowAccess() {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(
|
||||
false, Optional.of("certHash"), Optional.of("127.0.0.1"), certificateChecker);
|
||||
false,
|
||||
Optional.of("certHash"),
|
||||
Optional.of(InetAddresses.forString("127.0.0.1")),
|
||||
certificateChecker);
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
@@ -104,11 +112,33 @@ final class TlsCredentialsTest {
|
||||
.isEqualTo("Registrar IP address 127.0.0.1 is not in stored allow list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_missingIpAddress_doesntAllowAccess() {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(false, Optional.of("certHash"), Optional.empty(), certificateChecker);
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
.setClientCertificate(SAMPLE_CERT, clock.nowUtc())
|
||||
.setIpAddressAllowList(ImmutableSet.of(CidrAddressBlock.create("3.5.8.13")))
|
||||
.build());
|
||||
|
||||
BadRegistrarIpAddressException thrown =
|
||||
assertThrows(
|
||||
BadRegistrarIpAddressException.class,
|
||||
() -> tls.validate(Registrar.loadByRegistrarId("TheRegistrar").get(), "password"));
|
||||
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Registrar IP address is missing");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClientCertificate_notConfigured() {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(
|
||||
true, Optional.of("hash"), Optional.of("192.168.1.1"), certificateChecker);
|
||||
true,
|
||||
Optional.of("hash"),
|
||||
Optional.of(InetAddresses.forString("192.168.1.1")),
|
||||
certificateChecker);
|
||||
persistResource(loadRegistrar("TheRegistrar").asBuilder().build());
|
||||
assertThrows(
|
||||
RegistrarCertificateNotConfiguredException.class,
|
||||
@@ -119,7 +149,10 @@ final class TlsCredentialsTest {
|
||||
void test_validateCertificateHash_canBeConfiguredToBypassCerts() throws Exception {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(
|
||||
false, Optional.of("certHash"), Optional.of("192.168.1.1"), certificateChecker);
|
||||
false,
|
||||
Optional.of("certHash"),
|
||||
Optional.of(InetAddresses.forString("192.168.1.1")),
|
||||
certificateChecker);
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
@@ -134,7 +167,10 @@ final class TlsCredentialsTest {
|
||||
void test_validateCertificateHash_passWithFailOverCerticate() throws Exception {
|
||||
TlsCredentials tls =
|
||||
new TlsCredentials(
|
||||
false, Optional.of(SAMPLE_CERT_HASH), Optional.of("192.168.1.1"), certificateChecker);
|
||||
false,
|
||||
Optional.of(SAMPLE_CERT_HASH),
|
||||
Optional.of(InetAddresses.forString("192.168.1.1")),
|
||||
certificateChecker);
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
|
||||
@@ -30,6 +30,7 @@ import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.testing.CertificateSamples;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -42,10 +43,14 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
||||
Optional.of(CertificateSamples.SAMPLE_CERT3_HASH);
|
||||
private static final Optional<String> BAD_CERT_HASH =
|
||||
Optional.of(CertificateSamples.SAMPLE_CERT2_HASH);
|
||||
private static final Optional<String> GOOD_IP = Optional.of("192.168.1.1");
|
||||
private static final Optional<String> BAD_IP = Optional.of("1.1.1.1");
|
||||
private static final Optional<String> GOOD_IPV6 = Optional.of("2001:db8::1");
|
||||
private static final Optional<String> BAD_IPV6 = Optional.of("2001:db8::2");
|
||||
private static final Optional<InetAddress> GOOD_IP =
|
||||
Optional.of(InetAddresses.forString("192.168.1.1"));
|
||||
private static final Optional<InetAddress> BAD_IP =
|
||||
Optional.of(InetAddresses.forString("1.1.1.1"));
|
||||
private static final Optional<InetAddress> GOOD_IPV6 =
|
||||
Optional.of(InetAddresses.forString("2001:db8::1"));
|
||||
private static final Optional<InetAddress> BAD_IPV6 =
|
||||
Optional.of(InetAddresses.forString("2001:db8::2"));
|
||||
private final CertificateChecker certificateChecker =
|
||||
new CertificateChecker(
|
||||
ImmutableSortedMap.of(START_OF_TIME, 825, DateTime.parse("2020-09-01T00:00:00Z"), 398),
|
||||
@@ -59,8 +64,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
||||
protected Registrar.Builder getRegistrarBuilder() {
|
||||
return super.getRegistrarBuilder()
|
||||
.setClientCertificate(GOOD_CERT.get(), DateTime.now(UTC))
|
||||
.setIpAddressAllowList(
|
||||
ImmutableList.of(CidrAddressBlock.create(InetAddresses.forString(GOOD_IP.get()), 32)));
|
||||
.setIpAddressAllowList(ImmutableList.of(CidrAddressBlock.create(GOOD_IP.get(), 32)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +133,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
||||
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
|
||||
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
|
||||
.build());
|
||||
credentials = new TlsCredentials(true, GOOD_CERT_HASH, GOOD_CERT, certificateChecker);
|
||||
credentials = new TlsCredentials(true, GOOD_CERT_HASH, Optional.empty(), certificateChecker);
|
||||
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ public class GmailClientTest {
|
||||
assertThat(attachment.getContentType()).startsWith(CSV_UTF_8.toString());
|
||||
assertThat(attachment.getContentType()).endsWith("name=filename");
|
||||
assertThat(attachment.getContent()).isEqualTo("foo,bar\nbaz,qux");
|
||||
assertThat(attachment.getDisposition()).isEqualTo("attachment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.module.bsa;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class BsaServletTest {
|
||||
private final HttpServletRequest req = mock(HttpServletRequest.class);
|
||||
private final HttpServletResponse rsp = mock(HttpServletResponse.class);
|
||||
|
||||
@Test
|
||||
void testService_unknownPath_returnsNotFound() throws Exception {
|
||||
when(req.getMethod()).thenReturn("GET");
|
||||
when(req.getRequestURI()).thenReturn("/lol");
|
||||
new BsaServlet().service(req, rsp);
|
||||
verify(rsp).sendError(404);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ package google.registry.schema.integration;
|
||||
|
||||
import static com.google.common.truth.Truth.assert_;
|
||||
|
||||
import google.registry.bsa.persistence.BsaDomainInUseTest;
|
||||
import google.registry.bsa.persistence.BsaDownloadTest;
|
||||
import google.registry.bsa.persistence.BsaLabelTest;
|
||||
import google.registry.model.billing.BillingBaseTest;
|
||||
import google.registry.model.common.CursorTest;
|
||||
import google.registry.model.common.DnsRefreshRequestTest;
|
||||
@@ -82,6 +85,9 @@ import org.junit.runner.RunWith;
|
||||
BeforeSuiteTest.class,
|
||||
AllocationTokenTest.class,
|
||||
BillingBaseTest.class,
|
||||
BsaDomainInUseTest.class,
|
||||
BsaDownloadTest.class,
|
||||
BsaLabelTest.class,
|
||||
BulkPricingPackageTest.class,
|
||||
ClaimsListDaoTest.class,
|
||||
ContactHistoryTest.class,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -148,3 +148,4 @@ V147__drop_gaia_id_from_user.sql
|
||||
V148__add_bsa_download_and_label_tables.sql
|
||||
V149__add_bsa_domain_in_use_table.sql
|
||||
V150__add_tld_bsa_enroll_date.sql
|
||||
V151__add_bsa_unblockable_domain_table.sql
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
-- Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
CREATE TABLE "BsaUnblockableDomain" (
|
||||
label text not null,
|
||||
tld text not null,
|
||||
creation_time timestamptz not null,
|
||||
reason text not null,
|
||||
primary key (label, tld)
|
||||
);
|
||||
|
||||
ALTER TABLE IF EXISTS "BsaUnblockableDomain"
|
||||
ADD CONSTRAINT FKbsaunblockabledomainlabel
|
||||
FOREIGN KEY (label)
|
||||
REFERENCES "BsaLabel" (label)
|
||||
ON DELETE CASCADE;
|
||||
@@ -85,6 +85,29 @@
|
||||
primary key (billing_recurrence_id)
|
||||
);
|
||||
|
||||
create table "BsaDomainInUse" (
|
||||
label text not null,
|
||||
tld text not null,
|
||||
creation_time timestamptz not null,
|
||||
reason text not null,
|
||||
primary key (label, tld)
|
||||
);
|
||||
|
||||
create table "BsaDownload" (
|
||||
job_id bigserial not null,
|
||||
block_list_checksums text not null,
|
||||
creation_time timestamptz not null,
|
||||
stage text not null,
|
||||
update_timestamp timestamptz,
|
||||
primary key (job_id)
|
||||
);
|
||||
|
||||
create table "BsaLabel" (
|
||||
label text not null,
|
||||
creation_time timestamptz not null,
|
||||
primary key (label)
|
||||
);
|
||||
|
||||
create table "ClaimsEntry" (
|
||||
revision_id int8 not null,
|
||||
domain_label text not null,
|
||||
@@ -785,6 +808,7 @@ create index IDXoqttafcywwdn41um6kwlt0n8b on "BillingRecurrence" (domain_repo_id
|
||||
create index IDXp3usbtvk0v1m14i5tdp4xnxgc on "BillingRecurrence" (recurrence_end_time);
|
||||
create index IDXp0pxi708hlu4n40qhbtihge8x on "BillingRecurrence" (recurrence_last_expansion);
|
||||
create index IDXjny8wuot75b5e6p38r47wdawu on "BillingRecurrence" (recurrence_time_of_year);
|
||||
create index IDXj874kw19bgdnkxo1rue45jwlw on "BsaDownload" (creation_time);
|
||||
create index IDX3y752kr9uh4kh6uig54vemx0l on "Contact" (creation_time);
|
||||
create index IDXtm415d6fe1rr35stm33s5mg18 on "Contact" (current_sponsor_registrar_id);
|
||||
create index IDXn1f711wicdnooa2mqb7g1m55o on "Contact" (deletion_time);
|
||||
|
||||
@@ -177,6 +177,18 @@ CREATE TABLE public."BsaLabel" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaUnblockableDomain; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."BsaUnblockableDomain" (
|
||||
label text NOT NULL,
|
||||
tld text NOT NULL,
|
||||
creation_time timestamp with time zone NOT NULL,
|
||||
reason text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1343,6 +1355,14 @@ ALTER TABLE ONLY public."BsaLabel"
|
||||
ADD CONSTRAINT "BsaLabel_pkey" PRIMARY KEY (label);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaUnblockableDomain BsaUnblockableDomain_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BsaUnblockableDomain"
|
||||
ADD CONSTRAINT "BsaUnblockableDomain_pkey" PRIMARY KEY (label, tld);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry ClaimsEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2723,6 +2743,14 @@ ALTER TABLE ONLY public."BsaDomainInUse"
|
||||
ADD CONSTRAINT fkbsadomaininuse2label FOREIGN KEY (label) REFERENCES public."BsaLabel"(label) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaUnblockableDomain fkbsaunblockabledomainlabel; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BsaUnblockableDomain"
|
||||
ADD CONSTRAINT fkbsaunblockabledomainlabel FOREIGN KEY (label) REFERENCES public."BsaLabel"(label) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: DomainTransactionRecord fkcjqe54u72kha71vkibvxhjye7; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -66,6 +66,14 @@ sized to support not just the normal ongoing DNS load but also the load incurred
|
||||
by MapReduces, both scheduled (such as RDE) and on-demand (asynchronous
|
||||
contact/host deletion).
|
||||
|
||||
#### BSA service
|
||||
|
||||
The bsa service is responsible for business logic behind Nomulus and BSA
|
||||
functionality. Requests to the backend service are handled by the `BsaServlet`,
|
||||
which provides all of the endpoints exposed in `BsaRequestComponent`. These
|
||||
include tasks for downloading, processing and uploading BSA data.
|
||||
|
||||
|
||||
#### Tools service
|
||||
|
||||
The tools service is responsible for servicing requests from the `nomulus`
|
||||
|
||||
@@ -124,6 +124,7 @@ public class EppServiceHandler extends HttpsRelayServiceHandler {
|
||||
.headers()
|
||||
.set(ProxyHttpHeaders.CERTIFICATE_HASH, sslClientCertificateHash)
|
||||
.set(ProxyHttpHeaders.IP_ADDRESS, clientAddress)
|
||||
.set(ProxyHttpHeaders.FALLBACK_IP_ADDRESS, clientAddress)
|
||||
.set(HttpHeaderNames.CONTENT_TYPE, EPP_CONTENT_TYPE)
|
||||
.set(HttpHeaderNames.ACCEPT, EPP_CONTENT_TYPE);
|
||||
return request;
|
||||
|
||||
@@ -100,7 +100,8 @@ public final class TestUtils {
|
||||
.set(HttpHeaderNames.CONTENT_TYPE, "application/epp+xml")
|
||||
.set("accept", "application/epp+xml")
|
||||
.set(ProxyHttpHeaders.CERTIFICATE_HASH, sslClientCertificateHash)
|
||||
.set(ProxyHttpHeaders.IP_ADDRESS, clientAddress);
|
||||
.set(ProxyHttpHeaders.IP_ADDRESS, clientAddress)
|
||||
.set(ProxyHttpHeaders.FALLBACK_IP_ADDRESS, clientAddress);
|
||||
if (cookies.length != 0) {
|
||||
request.headers().set("cookie", ClientCookieEncoder.STRICT.encode(cookies));
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ else
|
||||
-PmavenUrl="${gcs_prefix}"/maven \
|
||||
-PpluginsUrl="${gcs_prefix}"/plugins
|
||||
|
||||
for service in default pubapi backend tools
|
||||
for service in default pubapi backend bsa tools
|
||||
do
|
||||
mv services/"${service}"/build/staged-app "${dest}/${service}"
|
||||
done
|
||||
|
||||
@@ -43,7 +43,7 @@ steps:
|
||||
|
||||
gcloud auth activate-service-account --key-file=tool-credential.json
|
||||
|
||||
for service in default pubapi backend tools
|
||||
for service in default pubapi backend bsa tools
|
||||
do
|
||||
for version in $(gcloud app versions list \
|
||||
--filter="SERVICE:$service AND SERVING_STATUS:STOPPED" \
|
||||
|
||||
@@ -75,7 +75,7 @@ steps:
|
||||
gcloud app versions list \
|
||||
--project $project_id --hide-no-traffic \
|
||||
--format="csv[no-heading](SERVICE,VERSION.ID)" | \
|
||||
grep -e "^backend\|^default\|^pubapi\|^tools" |\
|
||||
grep -e "^backend\|^default\|^bsa\|^pubapi\|^tools" |\
|
||||
while read line; do echo "${TAG_NAME},$line"; done | tee "$local_map"
|
||||
num_versions=$(cat "$local_map" | wc -l)
|
||||
if [ "$num_versions" -ne 4 ]; then
|
||||
|
||||
@@ -30,8 +30,7 @@ FROM gcr.io/${PROJECT_ID}/builder:${TAG_NAME}
|
||||
COPY deploy_sql_schema.sh /usr/local/bin/
|
||||
RUN \
|
||||
FLYWAY_MAVEN=https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline \
|
||||
&& FLYWAY_VERSION=$(curl ${FLYWAY_MAVEN}/maven-metadata.xml \
|
||||
| grep -oP "<release>\K.*(?=</release>)") \
|
||||
&& FLYWAY_VERSION="9.22.3" \
|
||||
&& echo "Downloading Flyway-commandline-${FLYWAY_VERSION}" \
|
||||
&& mkdir -p /flyway \
|
||||
&& curl -L ${FLYWAY_MAVEN}/${FLYWAY_VERSION}/flyway-commandline-${FLYWAY_VERSION}.tar.gz \
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
aopalliance:aopalliance:1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
args4j:args4j:2.0.23=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.101tec:zkclient:0.10=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.beust:jcommander:1.60=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.15.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:2.9.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-api:3.3.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport-zerodep:3.3.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport:3.3.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jffi:1.3.11=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-a64asm:1.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-constants:0.10.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-enxio:0.32.15=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-ffi:2.2.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-posix:3.1.17=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-unixsocket:0.38.20=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.android:annotations:4.1.1.4=runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:1.35.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:1.35.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:1.35.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:1.35.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.22.6-alpha=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:2.41.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.165.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.165.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.26.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.106.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.23.0-alpha=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:2.41.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.165.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.165.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.26.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.26.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.107.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,testCompileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.24.0=runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.106.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.12.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.23.0-alpha=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.113.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.113.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.24.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.18.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.16.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.32.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.32.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20230831-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20230520-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20230129-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20220920-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20230510-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20230806-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20230815-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20230831-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20230617-2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:1.9.86=runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.1.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.10.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.10.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.16.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:2.41.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.26.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.26.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.22.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.21.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.22.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:1.82.0=compileClasspath,testCompileClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.24.0=runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.124.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.12.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.45.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.22.6=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.4.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.common.html.types:types:1.0.6=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.dagger:dagger:2.48=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.21.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.escapevelocity:escapevelocity:0.9.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.flatbuffers:flatbuffers-java:1.12.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.flogger:flogger-system-backend:0.7.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.flogger:flogger:0.7.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.flogger:google-extensions:0.7.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava-parent:32.1.2-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:32.1.2-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.43.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:4.1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:metrics:1.0.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:stackdriver:1.0.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-appengine:1.34.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-java6:1.34.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.34.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.34.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.34.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.23.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.23.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.re2j:re2j:1.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.1.5=runtimeClasspath,testRuntimeClasspath
|
||||
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.ibm.icu:icu4j:57.1=compileClasspath,testCompileClasspath
|
||||
com.ibm.icu:icu4j:73.2=runtimeClasspath,testRuntimeClasspath
|
||||
com.jcraft:jsch:0.1.55=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.lmax:disruptor:3.4.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.sun.istack:istack-commons-runtime:3.0.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.15=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.paranamer:paranamer:2.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.zaxxer:HikariCP:3.4.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-codec:commons-codec:1.15=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-logging:commons-logging:1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
dnsjava:dnsjava:3.5.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.confluent:common-config:5.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.confluent:common-utils:5.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.confluent:kafka-avro-serializer:5.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.confluent:kafka-schema-registry-client:5.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.classgraph:classgraph:4.8.104=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.56.1=runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.56.1=runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.56.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.87.Final=runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.87.Final=runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-classes:2.0.52.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.87.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-metrics:0.31.0=compileClasspath,testCompileClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-metrics:0.31.1=runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-util:0.31.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-http-util:0.31.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-resource-util:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-exporter-metrics-util:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl:0.31.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.26.0=runtimeClasspath,testRuntimeClasspath
|
||||
javax.activation:activation:1.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.activation:javax.activation-api:1.2.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.annotation:jsr250-api:1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.inject:javax.inject:1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.mail:mail:1.5.0-b01=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.persistence:javax.persistence-api:2.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.servlet:servlet-api:2.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.validation:validation-api:1.0.0.GA=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.xml.bind:jaxb-api:2.3.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
jline:jline:1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
joda-time:joda-time:2.10.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.18=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.java.dev.jna:jna:5.12.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-format:5.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-memory-core:5.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:5.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.avro:avro:1.8.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-kafka:2.50.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_54_0:0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-csv:1.10.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.13.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpg-jdk15on:1.67=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk15on:1.67=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk15on:1.67=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.5=runtimeClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.33.0=compileClasspath,testCompileClasspath
|
||||
org.checkerframework:checker-qual:3.35.0=runtimeClasspath,testRuntimeClasspath
|
||||
org.codehaus.jackson:jackson-core-asl:1.9.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.jackson:jackson-mapper-asl:1.9.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-servlet:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util-ajax:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:9.4.49.v20220914=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:9.22.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.gwtproject:gwt-user:2.10.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hamcrest:hamcrest:2.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate.common:hibernate-commons-annotations:5.1.2.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-core:5.6.15.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-hikaricp:5.6.15.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jboss.logging:jboss-logging:3.4.3.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jboss:jandex:2.4.2.Final=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains:annotations:17.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.json:json:20230618=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.16.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.jvnet.staxex:stax-ex:1.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:9.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-tree:9.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-util:9.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:9.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.postgresql:postgresql:42.6.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:2.0.9=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-jdk14:2.0.9=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-core:5.3.27=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-expression:5.3.27=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-jcl:5.3.27=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.19.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.tukaani:xz:1.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.w3c.css:sac:1.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.xerial.snappy:snappy-java:1.1.10.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.10.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
xerces:xmlParserAPIs:2.6.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
xpp3:xpp3:1.1.4c=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
empty=annotationProcessor,providedCompile,providedRuntime,testAnnotationProcessor
|
||||
@@ -43,6 +43,7 @@ include 'proxy'
|
||||
include 'util'
|
||||
include 'services:default'
|
||||
include 'services:backend'
|
||||
include 'services:bsa'
|
||||
include 'services:tools'
|
||||
include 'services:pubapi'
|
||||
include 'java8compatibility'
|
||||
|
||||
@@ -19,30 +19,25 @@ import com.google.common.net.HttpHeaders;
|
||||
/** Utility class of HTTP header names used for HTTP calls between Nomulus and the proxy. */
|
||||
public final class ProxyHttpHeaders {
|
||||
|
||||
/**
|
||||
* HTTP header name used to pass a full SSL certificate from the proxy to Nomulus.
|
||||
*
|
||||
* <p>This header contains the SSL certificate encoded to a string. It is used to pass the client
|
||||
* certificate used for login to Nomulus for validation.
|
||||
*/
|
||||
public static final String FULL_CERTIFICATE = "X-SSL-Full-Certificate";
|
||||
|
||||
/** HTTP header name used to pass the certificate hash from the proxy to Nomulus. */
|
||||
public static final String CERTIFICATE_HASH = "X-SSL-Certificate";
|
||||
|
||||
/**
|
||||
* HTTP header name passed from Nomulus to proxy to indicate that a client has successfully logged
|
||||
* in.
|
||||
*/
|
||||
public static final String LOGGED_IN = "Logged-In";
|
||||
|
||||
/**
|
||||
* HTTP header name passed from Nomulus to proxy to indicate that an EPP session should be closed.
|
||||
*/
|
||||
public static final String EPP_SESSION = "Epp-Session";
|
||||
|
||||
/** HTTP header name used to pass the client IP address from the proxy to Nomulus. */
|
||||
public static final String IP_ADDRESS = HttpHeaders.X_FORWARDED_FOR;
|
||||
public static final String IP_ADDRESS = "Nomulus-Client-Address";
|
||||
|
||||
/**
|
||||
* Fallback HTTP header name used to pass the client IP address from the proxy to Nomulus.
|
||||
*
|
||||
* <p>Note that Java 17's servlet implementation (at least on App Engine) injects some seemingly
|
||||
* unrelated addresses into this header. We only use this as a fallback so the proxy can
|
||||
* transition to use the above header that should not be interfered with.
|
||||
*/
|
||||
public static final String FALLBACK_IP_ADDRESS = HttpHeaders.X_FORWARDED_FOR;
|
||||
|
||||
private ProxyHttpHeaders() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user