From e224a67eda4763117b4bd818332656de7889453d Mon Sep 17 00:00:00 2001 From: guyben Date: Mon, 17 Jul 2017 07:34:17 -0700 Subject: [PATCH] Change @Auth to an AutoValue, and created a set of predefined Auths We want to be safer and more explicit about the authentication needed by the many actions that exist. As such, we make the 'auth' parameter required in @Action (so it's always clear who can run a specific action) and we replace the @Auth with an enum so that only pre-approved configurations that are aptly named and documented can be used. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=162210306 --- .../backup/CommitLogCheckpointAction.java | 9 +- .../backup/DeleteOldCommitLogsAction.java | 6 +- .../backup/ExportCommitLogDiffAction.java | 9 +- .../backup/RestoreCommitLogsAction.java | 14 +- java/google/registry/batch/BUILD | 1 + .../batch/DeleteContactsAndHostsAction.java | 6 +- .../batch/DeleteProberDataAction.java | 7 +- .../ExpandRecurringBillingEventsAction.java | 6 +- .../batch/MapreduceEntityCleanupAction.java | 6 +- .../batch/RefreshDnsOnHostRenameAction.java | 6 +- .../batch/VerifyEntityIntegrityAction.java | 7 +- java/google/registry/cron/BUILD | 1 + .../registry/cron/CommitLogFanoutAction.java | 7 +- .../google/registry/cron/TldFanoutAction.java | 7 +- java/google/registry/dns/BUILD | 1 + .../registry/dns/PublishDnsUpdatesAction.java | 8 +- .../registry/dns/ReadDnsQueueAction.java | 7 +- .../google/registry/dns/RefreshDnsAction.java | 7 +- .../export/BigqueryPollJobAction.java | 9 +- .../registry/export/CheckSnapshotAction.java | 4 +- .../export/ExportDomainListsAction.java | 7 +- .../export/ExportReservedTermsAction.java | 7 +- .../registry/export/ExportSnapshotAction.java | 8 +- .../registry/export/LoadSnapshotAction.java | 7 +- .../export/PublishDetailReportAction.java | 10 +- .../export/SyncGroupMembersAction.java | 7 +- .../export/UpdateSnapshotViewAction.java | 8 +- java/google/registry/export/sheet/BUILD | 1 + .../sheet/SyncRegistrarsSheetAction.java | 7 +- .../google/registry/flows/CheckApiAction.java | 3 +- .../registry/flows/EppConsoleAction.java | 8 +- java/google/registry/flows/EppTlsAction.java | 8 +- java/google/registry/flows/EppToolAction.java | 8 +- .../registry/loadtest/LoadTestAction.java | 8 +- .../google/registry/monitoring/whitebox/BUILD | 1 + .../whitebox/MetricsExportAction.java | 7 +- .../registry/rdap/RdapAutnumAction.java | 3 +- .../registry/rdap/RdapDomainAction.java | 3 +- .../registry/rdap/RdapDomainSearchAction.java | 3 +- .../registry/rdap/RdapEntityAction.java | 3 +- .../registry/rdap/RdapEntitySearchAction.java | 3 +- java/google/registry/rdap/RdapHelpAction.java | 3 +- java/google/registry/rdap/RdapIpAction.java | 3 +- .../registry/rdap/RdapNameserverAction.java | 3 +- .../rdap/RdapNameserverSearchAction.java | 3 +- java/google/registry/rde/BUILD | 1 + java/google/registry/rde/BrdaCopyAction.java | 8 +- java/google/registry/rde/RdeReportAction.java | 7 +- .../google/registry/rde/RdeStagingAction.java | 4 +- java/google/registry/rde/RdeUploadAction.java | 7 +- java/google/registry/rde/imports/BUILD | 1 + .../rde/imports/RdeContactImportAction.java | 6 +- .../rde/imports/RdeDomainImportAction.java | 6 +- .../rde/imports/RdeHostImportAction.java | 6 +- .../rde/imports/RdeHostLinkAction.java | 6 +- .../reporting/IcannReportingUploadAction.java | 14 +- java/google/registry/request/Action.java | 2 +- .../registry/request/RequestHandler.java | 2 +- .../registry/request/RouterDisplayHelper.java | 10 +- java/google/registry/request/auth/Auth.java | 103 ++++++---- .../request/auth/RequestAuthenticator.java | 88 +++++++-- java/google/registry/tmch/BUILD | 1 + .../registry/tmch/NordnUploadAction.java | 8 +- .../registry/tmch/NordnVerifyAction.java | 8 +- java/google/registry/tmch/TmchCrlAction.java | 8 +- java/google/registry/tmch/TmchDnlAction.java | 8 +- .../google/registry/tmch/TmchSmdrlAction.java | 8 +- .../tools/server/CreateGroupsAction.java | 8 +- .../tools/server/CreatePremiumListAction.java | 8 +- .../tools/server/DeleteEntityAction.java | 8 +- .../tools/server/GenerateZoneFilesAction.java | 12 +- .../tools/server/KillAllCommitLogsAction.java | 7 +- .../server/KillAllEppResourcesAction.java | 7 +- .../tools/server/ListDomainsAction.java | 8 +- .../tools/server/ListHostsAction.java | 8 +- .../tools/server/ListPremiumListsAction.java | 8 +- .../tools/server/ListRegistrarsAction.java | 8 +- .../tools/server/ListReservedListsAction.java | 8 +- .../registry/tools/server/ListTldsAction.java | 8 +- .../server/RefreshDnsForAllDomainsAction.java | 8 +- .../server/ResaveAllEppResourcesAction.java | 8 +- .../tools/server/UpdatePremiumListAction.java | 8 +- .../tools/server/VerifyOteAction.java | 8 +- .../ui/server/registrar/ConsoleUiAction.java | 8 +- .../registrar/RegistrarPaymentAction.java | 8 +- .../RegistrarPaymentSetupAction.java | 8 +- .../registrar/RegistrarSettingsAction.java | 8 +- .../registry/whois/WhoisHttpServer.java | 3 +- java/google/registry/whois/WhoisServer.java | 8 +- .../frontend/testdata/frontend_routing.txt | 8 +- .../registry/request/RequestHandlerTest.java | 148 +++++++------- .../google/registry/request/RouterTest.java | 11 +- .../registry/request/auth/AuthTest.java | 31 +++ .../auth/RequestAuthenticatorTest.java | 182 ++++++++---------- 94 files changed, 614 insertions(+), 511 deletions(-) create mode 100644 javatests/google/registry/request/auth/AuthTest.java diff --git a/java/google/registry/backup/CommitLogCheckpointAction.java b/java/google/registry/backup/CommitLogCheckpointAction.java index 7d5538775..5bf6d5def 100644 --- a/java/google/registry/backup/CommitLogCheckpointAction.java +++ b/java/google/registry/backup/CommitLogCheckpointAction.java @@ -26,6 +26,7 @@ import com.googlecode.objectify.VoidWork; import google.registry.model.ofy.CommitLogCheckpoint; import google.registry.model.ofy.CommitLogCheckpointRoot; import google.registry.request.Action; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.TaskEnqueuer; @@ -43,9 +44,11 @@ import org.joda.time.DateTime; *

This action's supported method is GET rather than POST because it gets invoked via cron. */ @Action( - path = "/_dr/cron/commitLogCheckpoint", - method = Action.Method.GET, - automaticallyPrintOk = true) + path = "/_dr/cron/commitLogCheckpoint", + method = Action.Method.GET, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class CommitLogCheckpointAction implements Runnable { private static final FormattingLogger logger = getLoggerForCallerClass(); diff --git a/java/google/registry/backup/DeleteOldCommitLogsAction.java b/java/google/registry/backup/DeleteOldCommitLogsAction.java index 33dcb6f7f..52571c45f 100644 --- a/java/google/registry/backup/DeleteOldCommitLogsAction.java +++ b/java/google/registry/backup/DeleteOldCommitLogsAction.java @@ -37,6 +37,7 @@ import google.registry.model.ofy.CommitLogMutation; import google.registry.model.translators.CommitLogRevisionsTranslatorFactory; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import javax.inject.Inject; @@ -60,7 +61,10 @@ import org.joda.time.Duration; * EppResource. * */ -@Action(path = "/_dr/task/deleteOldCommitLogs") +@Action( + path = "/_dr/task/deleteOldCommitLogs", + auth = Auth.AUTH_INTERNAL_ONLY +) public final class DeleteOldCommitLogsAction implements Runnable { private static final int NUM_REDUCE_SHARDS = 10; diff --git a/java/google/registry/backup/ExportCommitLogDiffAction.java b/java/google/registry/backup/ExportCommitLogDiffAction.java index 53a3cda08..147abfe76 100644 --- a/java/google/registry/backup/ExportCommitLogDiffAction.java +++ b/java/google/registry/backup/ExportCommitLogDiffAction.java @@ -47,6 +47,7 @@ import google.registry.model.ofy.CommitLogManifest; import google.registry.model.ofy.CommitLogMutation; import google.registry.request.Action; import google.registry.request.Parameter; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.io.OutputStream; @@ -60,9 +61,11 @@ import org.joda.time.DateTime; /** Action that exports the diff between two commit log checkpoints to GCS. */ @Action( - path = ExportCommitLogDiffAction.PATH, - method = Action.Method.POST, - automaticallyPrintOk = true) + path = ExportCommitLogDiffAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class ExportCommitLogDiffAction implements Runnable { private static final FormattingLogger logger = getLoggerForCallerClass(); diff --git a/java/google/registry/backup/RestoreCommitLogsAction.java b/java/google/registry/backup/RestoreCommitLogsAction.java index d963733ad..f7665acbc 100644 --- a/java/google/registry/backup/RestoreCommitLogsAction.java +++ b/java/google/registry/backup/RestoreCommitLogsAction.java @@ -42,7 +42,6 @@ import google.registry.model.ofy.CommitLogMutation; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; import java.io.IOException; @@ -59,15 +58,10 @@ import org.joda.time.DateTime; /** Restore Registry 2 commit logs from GCS to Datastore. */ @Action( - path = RestoreCommitLogsAction.PATH, - method = Action.Method.POST, - automaticallyPrintOk = true, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + path = RestoreCommitLogsAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class RestoreCommitLogsAction implements Runnable { diff --git a/java/google/registry/batch/BUILD b/java/google/registry/batch/BUILD index ae92f08f2..16853707a 100644 --- a/java/google/registry/batch/BUILD +++ b/java/google/registry/batch/BUILD @@ -19,6 +19,7 @@ java_library( "//java/google/registry/pricing", "//java/google/registry/request", "//java/google/registry/request:modules", + "//java/google/registry/request/auth", "//java/google/registry/util", "//third_party/java/objectify:objectify-v4_1", "@com_google_apis_google_api_services_bigquery", diff --git a/java/google/registry/batch/DeleteContactsAndHostsAction.java b/java/google/registry/batch/DeleteContactsAndHostsAction.java index b47d7ee72..af2efab63 100644 --- a/java/google/registry/batch/DeleteContactsAndHostsAction.java +++ b/java/google/registry/batch/DeleteContactsAndHostsAction.java @@ -85,6 +85,7 @@ import google.registry.model.reporting.HistoryEntry; import google.registry.model.transfer.TransferStatus; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; @@ -103,7 +104,10 @@ import org.joda.time.DateTime; * over all domains and domain applications and checking for any references to the contacts/hosts in * pending deletion. */ -@Action(path = "/_dr/task/deleteContactsAndHosts") +@Action( + path = "/_dr/task/deleteContactsAndHosts", + auth = Auth.AUTH_INTERNAL_ONLY +) public class DeleteContactsAndHostsAction implements Runnable { static final String KIND_CONTACT = getKind(ContactResource.class); diff --git a/java/google/registry/batch/DeleteProberDataAction.java b/java/google/registry/batch/DeleteProberDataAction.java index 32626e01d..1dcaa51f4 100644 --- a/java/google/registry/batch/DeleteProberDataAction.java +++ b/java/google/registry/batch/DeleteProberDataAction.java @@ -40,6 +40,7 @@ import google.registry.model.registry.Registry.TldType; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.PipelineUtils; import java.util.List; @@ -51,7 +52,11 @@ import javax.inject.Inject; * *

See: https://www.youtube.com/watch?v=xuuv0syoHnM */ -@Action(path = "/_dr/task/deleteProberData", method = POST) +@Action( + path = "/_dr/task/deleteProberData", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class DeleteProberDataAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/batch/ExpandRecurringBillingEventsAction.java b/java/google/registry/batch/ExpandRecurringBillingEventsAction.java index 1cf85a879..03e2862ff 100644 --- a/java/google/registry/batch/ExpandRecurringBillingEventsAction.java +++ b/java/google/registry/batch/ExpandRecurringBillingEventsAction.java @@ -52,6 +52,7 @@ import google.registry.model.registry.Registry; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import java.util.Set; @@ -67,7 +68,10 @@ import org.joda.time.DateTime; * be expanded as a result of the job (the exclusive upper bound being the execution time of the * job). */ -@Action(path = "/_dr/task/expandRecurringBillingEvents") +@Action( + path = "/_dr/task/expandRecurringBillingEvents", + auth = Auth.AUTH_INTERNAL_ONLY +) public class ExpandRecurringBillingEventsAction implements Runnable { public static final String PARAM_CURSOR_TIME = "cursorTime"; diff --git a/java/google/registry/batch/MapreduceEntityCleanupAction.java b/java/google/registry/batch/MapreduceEntityCleanupAction.java index 7cbbc258d..54d63e8a4 100644 --- a/java/google/registry/batch/MapreduceEntityCleanupAction.java +++ b/java/google/registry/batch/MapreduceEntityCleanupAction.java @@ -25,6 +25,7 @@ import google.registry.mapreduce.MapreduceRunner; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import java.util.Set; @@ -69,7 +70,10 @@ import org.joda.time.DateTime; * are not in FINALIZED or STOPPED state. */ -@Action(path = "/_dr/task/mapreduceEntityCleanup") +@Action( + path = "/_dr/task/mapreduceEntityCleanup", + auth = Auth.AUTH_INTERNAL_ONLY +) public class MapreduceEntityCleanupAction implements Runnable { private static final int DEFAULT_DAYS_OLD = 180; diff --git a/java/google/registry/batch/RefreshDnsOnHostRenameAction.java b/java/google/registry/batch/RefreshDnsOnHostRenameAction.java index 9858e6588..14639c332 100644 --- a/java/google/registry/batch/RefreshDnsOnHostRenameAction.java +++ b/java/google/registry/batch/RefreshDnsOnHostRenameAction.java @@ -52,6 +52,7 @@ import google.registry.model.domain.DomainResource; import google.registry.model.host.HostResource; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; @@ -67,7 +68,10 @@ import javax.inject.Named; import org.joda.time.DateTime; /** Performs batched DNS refreshes for applicable domains following a host rename. */ -@Action(path = "/_dr/task/refreshDnsOnHostRename") +@Action( + path = "/_dr/task/refreshDnsOnHostRename", + auth = Auth.AUTH_INTERNAL_ONLY +) public class RefreshDnsOnHostRenameAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/batch/VerifyEntityIntegrityAction.java b/java/google/registry/batch/VerifyEntityIntegrityAction.java index 558921ce9..52b069842 100644 --- a/java/google/registry/batch/VerifyEntityIntegrityAction.java +++ b/java/google/registry/batch/VerifyEntityIntegrityAction.java @@ -59,6 +59,7 @@ import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex; import google.registry.model.transfer.TransferData.TransferServerApproveEntity; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; import java.io.Serializable; @@ -88,7 +89,11 @@ import org.joda.time.DateTime; * fullyQualifiedDomainName. * */ -@Action(path = "/_dr/task/verifyEntityIntegrity", method = POST) +@Action( + path = "/_dr/task/verifyEntityIntegrity", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class VerifyEntityIntegrityAction implements Runnable { private static final FormattingLogger logger = getLoggerForCallerClass(); diff --git a/java/google/registry/cron/BUILD b/java/google/registry/cron/BUILD index 8d512b5ec..21ac68160 100644 --- a/java/google/registry/cron/BUILD +++ b/java/google/registry/cron/BUILD @@ -10,6 +10,7 @@ java_library( deps = [ "//java/google/registry/model", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//third_party/java/objectify:objectify-v4_1", "@com_google_appengine_api_1_0_sdk", diff --git a/java/google/registry/cron/CommitLogFanoutAction.java b/java/google/registry/cron/CommitLogFanoutAction.java index 14daed58e..343bdf4ff 100644 --- a/java/google/registry/cron/CommitLogFanoutAction.java +++ b/java/google/registry/cron/CommitLogFanoutAction.java @@ -23,12 +23,17 @@ import com.google.common.base.Optional; import google.registry.model.ofy.CommitLogBucket; import google.registry.request.Action; import google.registry.request.Parameter; +import google.registry.request.auth.Auth; import google.registry.util.TaskEnqueuer; import java.util.Random; import javax.inject.Inject; /** Action for fanning out cron tasks for each commit log bucket. */ -@Action(path = "/_dr/cron/commitLogFanout", automaticallyPrintOk = true) +@Action( + path = "/_dr/cron/commitLogFanout", + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class CommitLogFanoutAction implements Runnable { public static final String BUCKET_PARAM = "bucket"; diff --git a/java/google/registry/cron/TldFanoutAction.java b/java/google/registry/cron/TldFanoutAction.java index c6a69f58d..f25222f34 100644 --- a/java/google/registry/cron/TldFanoutAction.java +++ b/java/google/registry/cron/TldFanoutAction.java @@ -41,6 +41,7 @@ import google.registry.request.Parameter; import google.registry.request.ParameterMap; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.TaskEnqueuer; import java.util.Random; import java.util.Set; @@ -70,7 +71,11 @@ import javax.inject.Inject; * This patharg is mostly useful for aesthetic purposes, since tasks are already namespaced. * */ -@Action(path = "/_dr/cron/fanout", automaticallyPrintOk = true) +@Action( + path = "/_dr/cron/fanout", + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class TldFanoutAction implements Runnable { private static final String ENDPOINT_PARAM = "endpoint"; diff --git a/java/google/registry/dns/BUILD b/java/google/registry/dns/BUILD index 9d2012fb9..bf4302773 100644 --- a/java/google/registry/dns/BUILD +++ b/java/google/registry/dns/BUILD @@ -25,6 +25,7 @@ java_library( "//java/google/registry/model", "//java/google/registry/monitoring/metrics", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//third_party/java/objectify:objectify-v4_1", "@com_google_appengine_api_1_0_sdk", diff --git a/java/google/registry/dns/PublishDnsUpdatesAction.java b/java/google/registry/dns/PublishDnsUpdatesAction.java index 436869ad5..6024e72e4 100644 --- a/java/google/registry/dns/PublishDnsUpdatesAction.java +++ b/java/google/registry/dns/PublishDnsUpdatesAction.java @@ -26,6 +26,7 @@ import google.registry.request.Action; import google.registry.request.HttpException.ServiceUnavailableException; import google.registry.request.Parameter; import google.registry.request.RequestParameters; +import google.registry.request.auth.Auth; import google.registry.util.DomainNameUtils; import google.registry.util.FormattingLogger; import java.util.Set; @@ -34,7 +35,12 @@ import javax.inject.Inject; import org.joda.time.Duration; /** Task that sends domain and host updates to the DNS server. */ -@Action(path = PublishDnsUpdatesAction.PATH, method = POST, automaticallyPrintOk = true) +@Action( + path = PublishDnsUpdatesAction.PATH, + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class PublishDnsUpdatesAction implements Runnable, Callable { public static final String PATH = "/_dr/task/publishDnsUpdates"; diff --git a/java/google/registry/dns/ReadDnsQueueAction.java b/java/google/registry/dns/ReadDnsQueueAction.java index ffc313a39..ec1460123 100644 --- a/java/google/registry/dns/ReadDnsQueueAction.java +++ b/java/google/registry/dns/ReadDnsQueueAction.java @@ -40,6 +40,7 @@ import google.registry.model.registry.Registry; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.TaskEnqueuer; import java.io.UnsupportedEncodingException; @@ -64,7 +65,11 @@ import org.joda.time.Duration; * not. * */ -@Action(path = "/_dr/cron/readDnsQueue", automaticallyPrintOk = true) +@Action( + path = "/_dr/cron/readDnsQueue", + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class ReadDnsQueueAction implements Runnable { public static final String KEEP_TASKS_PARAM = "keepTasks"; diff --git a/java/google/registry/dns/RefreshDnsAction.java b/java/google/registry/dns/RefreshDnsAction.java index 4c880d515..64920eb8b 100644 --- a/java/google/registry/dns/RefreshDnsAction.java +++ b/java/google/registry/dns/RefreshDnsAction.java @@ -26,11 +26,16 @@ import google.registry.request.Action; import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.NotFoundException; import google.registry.request.Parameter; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import javax.inject.Inject; /** Action that manually triggers refresh of DNS information. */ -@Action(path = "/_dr/dnsRefresh", automaticallyPrintOk = true) +@Action( + path = "/_dr/dnsRefresh", + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class RefreshDnsAction implements Runnable { @Inject Clock clock; diff --git a/java/google/registry/export/BigqueryPollJobAction.java b/java/google/registry/export/BigqueryPollJobAction.java index 836e4f4e9..5b957266f 100644 --- a/java/google/registry/export/BigqueryPollJobAction.java +++ b/java/google/registry/export/BigqueryPollJobAction.java @@ -31,6 +31,7 @@ import google.registry.request.Header; import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.NotModifiedException; import google.registry.request.Payload; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.TaskEnqueuer; import java.io.ByteArrayInputStream; @@ -46,9 +47,11 @@ import org.joda.time.Duration; * completion state; otherwise it will return a failure code so that the task will be retried. */ @Action( - path = BigqueryPollJobAction.PATH, - method = {Action.Method.GET, Action.Method.POST}, - automaticallyPrintOk = true) + path = BigqueryPollJobAction.PATH, + method = {Action.Method.GET, Action.Method.POST}, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public class BigqueryPollJobAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/export/CheckSnapshotAction.java b/java/google/registry/export/CheckSnapshotAction.java index 0b9a357c7..540128728 100644 --- a/java/google/registry/export/CheckSnapshotAction.java +++ b/java/google/registry/export/CheckSnapshotAction.java @@ -36,6 +36,7 @@ import google.registry.request.HttpException.NotModifiedException; import google.registry.request.Parameter; import google.registry.request.RequestMethod; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.util.Set; import javax.inject.Inject; @@ -49,7 +50,8 @@ import org.joda.time.format.PeriodFormat; @Action( path = CheckSnapshotAction.PATH, method = {POST, GET}, - automaticallyPrintOk = true + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY ) public class CheckSnapshotAction implements Runnable { diff --git a/java/google/registry/export/ExportDomainListsAction.java b/java/google/registry/export/ExportDomainListsAction.java index afd2c7976..74fa257f9 100644 --- a/java/google/registry/export/ExportDomainListsAction.java +++ b/java/google/registry/export/ExportDomainListsAction.java @@ -37,6 +37,7 @@ import google.registry.model.domain.DomainResource; import google.registry.model.registry.Registry.TldType; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.io.OutputStream; @@ -52,7 +53,11 @@ import org.joda.time.DateTime; * Each TLD's active domain names are exported as a newline-delimited flat text file with the name * TLD.txt into the domain-lists bucket. Note that this overwrites the files in place. */ -@Action(path = "/_dr/task/exportDomainLists", method = POST) +@Action( + path = "/_dr/task/exportDomainLists", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class ExportDomainListsAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/export/ExportReservedTermsAction.java b/java/google/registry/export/ExportReservedTermsAction.java index 55dbd4f10..5eed08047 100644 --- a/java/google/registry/export/ExportReservedTermsAction.java +++ b/java/google/registry/export/ExportReservedTermsAction.java @@ -27,12 +27,17 @@ import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.storage.drive.DriveConnection; import google.registry.util.FormattingLogger; import javax.inject.Inject; /** Action that exports the publicly viewable reserved terms list for a TLD to Google Drive. */ -@Action(path = "/_dr/task/exportReservedTerms", method = POST) +@Action( + path = "/_dr/task/exportReservedTerms", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class ExportReservedTermsAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/export/ExportSnapshotAction.java b/java/google/registry/export/ExportSnapshotAction.java index 15213d6cd..2bfb2f03e 100644 --- a/java/google/registry/export/ExportSnapshotAction.java +++ b/java/google/registry/export/ExportSnapshotAction.java @@ -20,6 +20,7 @@ import static google.registry.request.Action.Method.POST; import google.registry.config.RegistryConfig; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import javax.inject.Inject; @@ -37,7 +38,12 @@ import javax.inject.Inject; *

  • The {@link UpdateSnapshotViewAction} updates the view in latest_snapshot. * */ -@Action(path = ExportSnapshotAction.PATH, method = POST, automaticallyPrintOk = true) +@Action( + path = ExportSnapshotAction.PATH, + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public class ExportSnapshotAction implements Runnable { /** Queue to use for enqueuing the task that will actually launch the backup. */ diff --git a/java/google/registry/export/LoadSnapshotAction.java b/java/google/registry/export/LoadSnapshotAction.java index c2ac261de..402637aa5 100644 --- a/java/google/registry/export/LoadSnapshotAction.java +++ b/java/google/registry/export/LoadSnapshotAction.java @@ -43,6 +43,7 @@ import google.registry.request.Action; import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.InternalServerErrorException; import google.registry.request.Parameter; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import java.io.IOException; @@ -50,7 +51,11 @@ import javax.inject.Inject; import org.joda.time.DateTime; /** Action to load a Datastore snapshot from Google Cloud Storage into BigQuery. */ -@Action(path = LoadSnapshotAction.PATH, method = POST) +@Action( + path = LoadSnapshotAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class LoadSnapshotAction implements Runnable { /** Parameter names for passing parameters into the servlet. */ diff --git a/java/google/registry/export/PublishDetailReportAction.java b/java/google/registry/export/PublishDetailReportAction.java index 62a3fe41f..1c58ab7ee 100644 --- a/java/google/registry/export/PublishDetailReportAction.java +++ b/java/google/registry/export/PublishDetailReportAction.java @@ -29,9 +29,6 @@ import google.registry.request.HttpException.InternalServerErrorException; import google.registry.request.JsonActionRunner; import google.registry.request.JsonActionRunner.JsonAction; import google.registry.request.auth.Auth; -import google.registry.request.auth.Auth.AuthMethod; -import google.registry.request.auth.Auth.UserPolicy; -import google.registry.request.auth.AuthLevel; import google.registry.storage.drive.DriveConnection; import google.registry.util.FormattingLogger; import java.io.FileNotFoundException; @@ -43,12 +40,7 @@ import javax.inject.Inject; @Action( path = PublishDetailReportAction.PATH, method = Action.Method.POST, - auth = - @Auth( - methods = {AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class PublishDetailReportAction implements Runnable, JsonAction { diff --git a/java/google/registry/export/SyncGroupMembersAction.java b/java/google/registry/export/SyncGroupMembersAction.java index e4392760d..2d6f399e4 100644 --- a/java/google/registry/export/SyncGroupMembersAction.java +++ b/java/google/registry/export/SyncGroupMembersAction.java @@ -36,6 +36,7 @@ import google.registry.model.registrar.Registrar; import google.registry.model.registrar.RegistrarContact; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; import java.io.IOException; @@ -52,7 +53,11 @@ import javax.inject.Inject; * *

    This uses the Directory API. */ -@Action(path = "/_dr/task/syncGroupMembers", method = POST) +@Action( + path = "/_dr/task/syncGroupMembers", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class SyncGroupMembersAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/export/UpdateSnapshotViewAction.java b/java/google/registry/export/UpdateSnapshotViewAction.java index 46293f0e7..129e1badb 100644 --- a/java/google/registry/export/UpdateSnapshotViewAction.java +++ b/java/google/registry/export/UpdateSnapshotViewAction.java @@ -13,6 +13,7 @@ // limitations under the License. package google.registry.export; + import static google.registry.request.Action.Method.POST; import com.google.api.client.googleapis.json.GoogleJsonResponseException; @@ -27,13 +28,18 @@ import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; import google.registry.request.HttpException.InternalServerErrorException; import google.registry.request.Parameter; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.SqlTemplate; import java.io.IOException; import javax.inject.Inject; /** Update a well-known view to point at a certain Datastore snapshot table in BigQuery. */ -@Action(path = UpdateSnapshotViewAction.PATH, method = POST) +@Action( + path = UpdateSnapshotViewAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class UpdateSnapshotViewAction implements Runnable { /** Headers for passing parameters into the servlet. */ diff --git a/java/google/registry/export/sheet/BUILD b/java/google/registry/export/sheet/BUILD index ffb9e1846..fb45794d8 100644 --- a/java/google/registry/export/sheet/BUILD +++ b/java/google/registry/export/sheet/BUILD @@ -11,6 +11,7 @@ java_library( "//java/google/registry/config", "//java/google/registry/model", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//third_party/java/objectify:objectify-v4_1", "@com_google_api_client", diff --git a/java/google/registry/export/sheet/SyncRegistrarsSheetAction.java b/java/google/registry/export/sheet/SyncRegistrarsSheetAction.java index c0da8e083..1d94e927a 100644 --- a/java/google/registry/export/sheet/SyncRegistrarsSheetAction.java +++ b/java/google/registry/export/sheet/SyncRegistrarsSheetAction.java @@ -34,6 +34,7 @@ import google.registry.model.server.Lock; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; import java.io.IOException; @@ -60,7 +61,11 @@ import org.joda.time.Duration; * * @see SyncRegistrarsSheet */ -@Action(path = SyncRegistrarsSheetAction.PATH, method = POST) +@Action( + path = SyncRegistrarsSheetAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class SyncRegistrarsSheetAction implements Runnable { private enum Result { diff --git a/java/google/registry/flows/CheckApiAction.java b/java/google/registry/flows/CheckApiAction.java index 7677fea26..46f69d0ab 100644 --- a/java/google/registry/flows/CheckApiAction.java +++ b/java/google/registry/flows/CheckApiAction.java @@ -46,7 +46,6 @@ import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import java.util.Map; import javax.inject.Inject; @@ -61,7 +60,7 @@ import javax.servlet.http.HttpServletRequest; */ @Action( path = "/check", - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class CheckApiAction implements Runnable { diff --git a/java/google/registry/flows/EppConsoleAction.java b/java/google/registry/flows/EppConsoleAction.java index 19e4b8302..5d37c4089 100644 --- a/java/google/registry/flows/EppConsoleAction.java +++ b/java/google/registry/flows/EppConsoleAction.java @@ -19,7 +19,6 @@ import google.registry.request.Action; import google.registry.request.Action.Method; import google.registry.request.Payload; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; import javax.servlet.http.HttpSession; @@ -27,12 +26,7 @@ import javax.servlet.http.HttpSession; @Action( path = "/registrar-xhr", method = Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC - ) + auth = Auth.AUTH_PUBLIC_LOGGED_IN ) public class EppConsoleAction implements Runnable { diff --git a/java/google/registry/flows/EppTlsAction.java b/java/google/registry/flows/EppTlsAction.java index 87874100d..8163eed76 100644 --- a/java/google/registry/flows/EppTlsAction.java +++ b/java/google/registry/flows/EppTlsAction.java @@ -18,7 +18,6 @@ import google.registry.request.Action; import google.registry.request.Action.Method; import google.registry.request.Payload; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import javax.inject.Inject; import javax.servlet.http.HttpSession; @@ -30,12 +29,7 @@ import javax.servlet.http.HttpSession; @Action( path = "/_dr/epp", method = Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class EppTlsAction implements Runnable { diff --git a/java/google/registry/flows/EppToolAction.java b/java/google/registry/flows/EppToolAction.java index 5155275b1..efc9706f6 100644 --- a/java/google/registry/flows/EppToolAction.java +++ b/java/google/registry/flows/EppToolAction.java @@ -25,7 +25,6 @@ import google.registry.request.Action; import google.registry.request.Action.Method; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; @@ -33,12 +32,7 @@ import javax.servlet.http.HttpServletRequest; @Action( path = "/_dr/epptool", method = Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class EppToolAction implements Runnable { diff --git a/java/google/registry/loadtest/LoadTestAction.java b/java/google/registry/loadtest/LoadTestAction.java index ae920ae01..e0765c954 100644 --- a/java/google/registry/loadtest/LoadTestAction.java +++ b/java/google/registry/loadtest/LoadTestAction.java @@ -34,7 +34,6 @@ import google.registry.config.RegistryEnvironment; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.security.XsrfTokenManager; import google.registry.util.FormattingLogger; import google.registry.util.TaskEnqueuer; @@ -58,12 +57,7 @@ import org.joda.time.DateTime; path = LoadTestAction.PATH, method = Action.Method.POST, automaticallyPrintOk = true, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class LoadTestAction implements Runnable { diff --git a/java/google/registry/monitoring/whitebox/BUILD b/java/google/registry/monitoring/whitebox/BUILD index 92274deb7..dbfc1e4fd 100644 --- a/java/google/registry/monitoring/whitebox/BUILD +++ b/java/google/registry/monitoring/whitebox/BUILD @@ -14,6 +14,7 @@ java_library( "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/metrics/stackdriver", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//third_party/java/objectify:objectify-v4_1", "@com_google_apis_google_api_services_bigquery", diff --git a/java/google/registry/monitoring/whitebox/MetricsExportAction.java b/java/google/registry/monitoring/whitebox/MetricsExportAction.java index 19ac025d4..36f4f2bb5 100644 --- a/java/google/registry/monitoring/whitebox/MetricsExportAction.java +++ b/java/google/registry/monitoring/whitebox/MetricsExportAction.java @@ -36,13 +36,18 @@ import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.ParameterMap; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.util.Map; import javax.inject.Inject; /** Action for exporting metrics to BigQuery. */ -@Action(path = MetricsExportAction.PATH, method = POST) +@Action( + path = MetricsExportAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class MetricsExportAction implements Runnable { public static final String PATH = "/_dr/task/metrics"; diff --git a/java/google/registry/rdap/RdapAutnumAction.java b/java/google/registry/rdap/RdapAutnumAction.java index 50ee6e4f7..8bac68e37 100644 --- a/java/google/registry/rdap/RdapAutnumAction.java +++ b/java/google/registry/rdap/RdapAutnumAction.java @@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableMap; import google.registry.request.Action; import google.registry.request.HttpException.NotImplementedException; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** @@ -34,7 +33,7 @@ import javax.inject.Inject; path = RdapAutnumAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapAutnumAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapDomainAction.java b/java/google/registry/rdap/RdapDomainAction.java index 796474005..e9fba3776 100644 --- a/java/google/registry/rdap/RdapDomainAction.java +++ b/java/google/registry/rdap/RdapDomainAction.java @@ -24,7 +24,6 @@ import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.request.Action; import google.registry.request.HttpException.NotFoundException; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -34,7 +33,7 @@ import org.joda.time.DateTime; path = RdapDomainAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapDomainAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapDomainSearchAction.java b/java/google/registry/rdap/RdapDomainSearchAction.java index 03cf31c05..a9aa8bf54 100644 --- a/java/google/registry/rdap/RdapDomainSearchAction.java +++ b/java/google/registry/rdap/RdapDomainSearchAction.java @@ -42,7 +42,6 @@ import google.registry.request.HttpException.NotFoundException; import google.registry.request.HttpException.UnprocessableEntityException; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.Idn; @@ -66,7 +65,7 @@ import org.joda.time.DateTime; @Action( path = RdapDomainSearchAction.PATH, method = {GET, HEAD}, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapDomainSearchAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapEntityAction.java b/java/google/registry/rdap/RdapEntityAction.java index 0fb1a38f4..d7998cd4e 100644 --- a/java/google/registry/rdap/RdapEntityAction.java +++ b/java/google/registry/rdap/RdapEntityAction.java @@ -32,7 +32,6 @@ import google.registry.request.Action; import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.NotFoundException; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -51,7 +50,7 @@ import org.joda.time.DateTime; path = RdapEntityAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapEntityAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapEntitySearchAction.java b/java/google/registry/rdap/RdapEntitySearchAction.java index d3a928280..11b0ab66a 100644 --- a/java/google/registry/rdap/RdapEntitySearchAction.java +++ b/java/google/registry/rdap/RdapEntitySearchAction.java @@ -41,7 +41,6 @@ import google.registry.request.HttpException.NotFoundException; import google.registry.request.HttpException.UnprocessableEntityException; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import java.util.ArrayList; import java.util.List; @@ -61,7 +60,7 @@ import org.joda.time.DateTime; @Action( path = RdapEntitySearchAction.PATH, method = {GET, HEAD}, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapEntitySearchAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapHelpAction.java b/java/google/registry/rdap/RdapHelpAction.java index e1f4cfffe..abde91d06 100644 --- a/java/google/registry/rdap/RdapHelpAction.java +++ b/java/google/registry/rdap/RdapHelpAction.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap; import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import javax.inject.Inject; @@ -31,7 +30,7 @@ import javax.inject.Inject; path = RdapHelpAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapHelpAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapIpAction.java b/java/google/registry/rdap/RdapIpAction.java index 08624d64f..255ef954e 100644 --- a/java/google/registry/rdap/RdapIpAction.java +++ b/java/google/registry/rdap/RdapIpAction.java @@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableMap; import google.registry.request.Action; import google.registry.request.HttpException.NotImplementedException; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** @@ -34,7 +33,7 @@ import javax.inject.Inject; path = RdapIpAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapIpAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapNameserverAction.java b/java/google/registry/rdap/RdapNameserverAction.java index 362f76d5e..4ec89ef7f 100644 --- a/java/google/registry/rdap/RdapNameserverAction.java +++ b/java/google/registry/rdap/RdapNameserverAction.java @@ -24,7 +24,6 @@ import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.request.Action; import google.registry.request.HttpException.NotFoundException; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -34,7 +33,7 @@ import org.joda.time.DateTime; path = RdapNameserverAction.PATH, method = {GET, HEAD}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapNameserverAction extends RdapActionBase { diff --git a/java/google/registry/rdap/RdapNameserverSearchAction.java b/java/google/registry/rdap/RdapNameserverSearchAction.java index 50a34f805..de6db742c 100644 --- a/java/google/registry/rdap/RdapNameserverSearchAction.java +++ b/java/google/registry/rdap/RdapNameserverSearchAction.java @@ -37,7 +37,6 @@ import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.NotFoundException; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import google.registry.util.Idn; import java.net.InetAddress; @@ -58,7 +57,7 @@ import org.joda.time.DateTime; @Action( path = RdapNameserverSearchAction.PATH, method = {GET, HEAD}, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public class RdapNameserverSearchAction extends RdapActionBase { diff --git a/java/google/registry/rde/BUILD b/java/google/registry/rde/BUILD index a0156c635..d3d68ca97 100644 --- a/java/google/registry/rde/BUILD +++ b/java/google/registry/rde/BUILD @@ -15,6 +15,7 @@ java_library( "//java/google/registry/mapreduce/inputs", "//java/google/registry/model", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/tldconfig/idn", "//java/google/registry/util", "//java/google/registry/xjc", diff --git a/java/google/registry/rde/BrdaCopyAction.java b/java/google/registry/rde/BrdaCopyAction.java index 5c3cba7ec..358fb5cca 100644 --- a/java/google/registry/rde/BrdaCopyAction.java +++ b/java/google/registry/rde/BrdaCopyAction.java @@ -27,6 +27,7 @@ import google.registry.model.rde.RdeNamingUtils; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.BufferedInputStream; import java.io.IOException; @@ -52,7 +53,12 @@ import org.joda.time.DateTime; * * @see Registry Agreement */ -@Action(path = BrdaCopyAction.PATH, method = POST, automaticallyPrintOk = true) +@Action( + path = BrdaCopyAction.PATH, + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class BrdaCopyAction implements Runnable { static final String PATH = "/_dr/task/brdaCopy"; diff --git a/java/google/registry/rde/RdeReportAction.java b/java/google/registry/rde/RdeReportAction.java index 58a2c493f..fefcfb71c 100644 --- a/java/google/registry/rde/RdeReportAction.java +++ b/java/google/registry/rde/RdeReportAction.java @@ -36,6 +36,7 @@ import google.registry.request.HttpException.NoContentException; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.io.InputStream; @@ -48,7 +49,11 @@ import org.joda.time.Duration; /** * Action that uploads a small XML RDE report to ICANN after {@link RdeUploadAction} has finished. */ -@Action(path = RdeReportAction.PATH, method = POST) +@Action( + path = RdeReportAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class RdeReportAction implements Runnable, EscrowTask { static final String PATH = "/_dr/task/rdeReport"; diff --git a/java/google/registry/rde/RdeStagingAction.java b/java/google/registry/rde/RdeStagingAction.java index 28b7cca06..9b7708816 100644 --- a/java/google/registry/rde/RdeStagingAction.java +++ b/java/google/registry/rde/RdeStagingAction.java @@ -45,6 +45,7 @@ import google.registry.request.HttpException.BadRequestException; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import javax.inject.Inject; @@ -187,7 +188,8 @@ import org.joda.time.Duration; */ @Action( path = RdeStagingAction.PATH, - method = {GET, POST} + method = {GET, POST}, + auth = Auth.AUTH_INTERNAL_ONLY ) public final class RdeStagingAction implements Runnable { diff --git a/java/google/registry/rde/RdeUploadAction.java b/java/google/registry/rde/RdeUploadAction.java index 07bd4da94..b2dda593d 100644 --- a/java/google/registry/rde/RdeUploadAction.java +++ b/java/google/registry/rde/RdeUploadAction.java @@ -48,6 +48,7 @@ import google.registry.request.HttpException.ServiceUnavailableException; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; @@ -77,7 +78,11 @@ import org.joda.time.Duration; *

    Once this action completes, it rolls the cursor forward a day and triggers * {@link RdeReportAction}. */ -@Action(path = RdeUploadAction.PATH, method = POST) +@Action( + path = RdeUploadAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class RdeUploadAction implements Runnable, EscrowTask { static final String PATH = "/_dr/task/rdeUpload"; diff --git a/java/google/registry/rde/imports/BUILD b/java/google/registry/rde/imports/BUILD index b6f0516b0..fb594b3ee 100644 --- a/java/google/registry/rde/imports/BUILD +++ b/java/google/registry/rde/imports/BUILD @@ -16,6 +16,7 @@ java_library( "//java/google/registry/model", "//java/google/registry/pricing", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//java/google/registry/xjc", "//java/google/registry/xml", diff --git a/java/google/registry/rde/imports/RdeContactImportAction.java b/java/google/registry/rde/imports/RdeContactImportAction.java index e97ef23d1..7b4b56d24 100644 --- a/java/google/registry/rde/imports/RdeContactImportAction.java +++ b/java/google/registry/rde/imports/RdeContactImportAction.java @@ -33,6 +33,7 @@ import google.registry.model.contact.ContactResource; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.SystemClock; import google.registry.xjc.JaxbFragment; @@ -45,7 +46,10 @@ import javax.inject.Inject; * *

    Specify the escrow file to import with the "path" parameter. */ -@Action(path = "/_dr/task/importRdeContacts") +@Action( + path = "/_dr/task/importRdeContacts", + auth = Auth.AUTH_INTERNAL_ONLY +) public class RdeContactImportAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/rde/imports/RdeDomainImportAction.java b/java/google/registry/rde/imports/RdeDomainImportAction.java index 47218e0d5..a249528c3 100644 --- a/java/google/registry/rde/imports/RdeDomainImportAction.java +++ b/java/google/registry/rde/imports/RdeDomainImportAction.java @@ -50,6 +50,7 @@ import google.registry.model.transfer.TransferStatus; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.SystemClock; import google.registry.xjc.JaxbFragment; @@ -63,7 +64,10 @@ import org.joda.money.Money; * *

    Specify the escrow file to import with the "path" parameter. */ -@Action(path = "/_dr/task/importRdeDomains") +@Action( + path = "/_dr/task/importRdeDomains", + auth = Auth.AUTH_INTERNAL_ONLY +) public class RdeDomainImportAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/rde/imports/RdeHostImportAction.java b/java/google/registry/rde/imports/RdeHostImportAction.java index bc81bb18d..d3b07f978 100644 --- a/java/google/registry/rde/imports/RdeHostImportAction.java +++ b/java/google/registry/rde/imports/RdeHostImportAction.java @@ -33,6 +33,7 @@ import google.registry.model.host.HostResource; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.SystemClock; import google.registry.xjc.JaxbFragment; @@ -45,7 +46,10 @@ import javax.inject.Inject; * *

    Specify the escrow file to import with the "path" parameter. */ -@Action(path = "/_dr/task/importRdeHosts") +@Action( + path = "/_dr/task/importRdeHosts", + auth = Auth.AUTH_INTERNAL_ONLY +) public class RdeHostImportAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/rde/imports/RdeHostLinkAction.java b/java/google/registry/rde/imports/RdeHostLinkAction.java index 512f8d109..5c5c25341 100644 --- a/java/google/registry/rde/imports/RdeHostLinkAction.java +++ b/java/google/registry/rde/imports/RdeHostLinkAction.java @@ -33,6 +33,7 @@ import google.registry.model.host.HostResource; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.xjc.JaxbFragment; import google.registry.xjc.rdehost.XjcRdeHost; @@ -51,7 +52,10 @@ import org.joda.time.DateTime; * *

    Specify the escrow file to import with the "path" parameter. */ -@Action(path = "/_dr/task/linkRdeHosts") +@Action( + path = "/_dr/task/linkRdeHosts", + auth = Auth.AUTH_INTERNAL_ONLY +) public class RdeHostLinkAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/reporting/IcannReportingUploadAction.java b/java/google/registry/reporting/IcannReportingUploadAction.java index 00c8bda27..60eabc9d0 100644 --- a/java/google/registry/reporting/IcannReportingUploadAction.java +++ b/java/google/registry/reporting/IcannReportingUploadAction.java @@ -30,9 +30,6 @@ import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.Auth.AuthMethod; -import google.registry.request.auth.Auth.UserPolicy; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; import google.registry.xml.XmlException; @@ -48,14 +45,9 @@ import javax.inject.Inject; * */ @Action( - path = IcannReportingUploadAction.PATH, - method = POST, - auth = - @Auth( - methods = {AuthMethod.INTERNAL, AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = UserPolicy.ADMIN - ) + path = IcannReportingUploadAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class IcannReportingUploadAction implements Runnable { diff --git a/java/google/registry/request/Action.java b/java/google/registry/request/Action.java index 192652649..9427222e2 100644 --- a/java/google/registry/request/Action.java +++ b/java/google/registry/request/Action.java @@ -47,5 +47,5 @@ public @interface Action { boolean automaticallyPrintOk() default false; /** Authentication settings. */ - Auth auth() default @Auth; + Auth auth(); } diff --git a/java/google/registry/request/RequestHandler.java b/java/google/registry/request/RequestHandler.java index f13dbfe74..6b8d40173 100644 --- a/java/google/registry/request/RequestHandler.java +++ b/java/google/registry/request/RequestHandler.java @@ -132,7 +132,7 @@ public class RequestHandler { return; } Optional authResult = - requestAuthenticator.authorize(route.get().action().auth(), req); + requestAuthenticator.authorize(route.get().action().auth().authSettings(), req); if (!authResult.isPresent()) { rsp.sendError(SC_FORBIDDEN, "Not authorized"); return; diff --git a/java/google/registry/request/RouterDisplayHelper.java b/java/google/registry/request/RouterDisplayHelper.java index 6d8452834..519f29ce3 100644 --- a/java/google/registry/request/RouterDisplayHelper.java +++ b/java/google/registry/request/RouterDisplayHelper.java @@ -90,9 +90,9 @@ public class RouterDisplayHelper { route.actionClass().getSimpleName(), Joiner.on(",").join(route.action().method()), route.action().automaticallyPrintOk() ? "y" : "n", - Joiner.on(",").join(route.action().auth().methods()), - route.action().auth().minimumLevel(), - route.action().auth().userPolicy()); + Joiner.on(",").join(route.action().auth().authSettings().methods()), + route.action().auth().authSettings().minimumLevel(), + route.action().auth().authSettings().userPolicy()); } private static String formatRoutes(Iterable routes) { @@ -119,11 +119,11 @@ public class RouterDisplayHelper { if (len > methodsWidth) { methodsWidth = len; } - len = Joiner.on(",").join(route.action().auth().methods()).length(); + len = Joiner.on(",").join(route.action().auth().authSettings().methods()).length(); if (len > authMethodsWidth) { authMethodsWidth = len; } - len = route.action().auth().minimumLevel().toString().length(); + len = route.action().auth().authSettings().minimumLevel().toString().length(); if (len > minLevelWidth) { minLevelWidth = len; } diff --git a/java/google/registry/request/auth/Auth.java b/java/google/registry/request/auth/Auth.java index fdd698e75..ccc065c9b 100644 --- a/java/google/registry/request/auth/Auth.java +++ b/java/google/registry/request/auth/Auth.java @@ -14,53 +14,74 @@ package google.registry.request.auth; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import com.google.common.collect.ImmutableList; +import google.registry.request.auth.RequestAuthenticator.AuthMethod; +import google.registry.request.auth.RequestAuthenticator.AuthSettings; +import google.registry.request.auth.RequestAuthenticator.UserPolicy; -/** Annotation used to configure authentication settings for Actions. */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface Auth { +/** Enum used to configure authentication settings for Actions. */ +public enum Auth { - /** Available methods for authentication. */ - public enum AuthMethod { + /** + * Allows anyone access, doesn't attempt to authenticate user. + * + * Will never return absent(), but only authenticates access from App Engine task-queues. For + * everyone else - returns NOT_AUTHENTICATED. + */ + AUTH_PUBLIC_ANONYMOUS( + ImmutableList.of(AuthMethod.INTERNAL), + AuthLevel.NONE, + UserPolicy.PUBLIC), - /** App Engine internal authentication. Must always be provided as the first method. */ - INTERNAL, + /** + * Allows anyone access, does attempt to authenticate user. + * + * If a user is logged in, will authenticate (and return) them. Otherwise, access is still + * granted, but NOT_AUTHENTICATED is returned. + * + * Will never return absent(). + */ + AUTH_PUBLIC( + ImmutableList.of(AuthMethod.INTERNAL, AuthMethod.API, AuthMethod.LEGACY), + AuthLevel.NONE, + UserPolicy.PUBLIC), - /** Authentication methods suitable for API-style access, such as OAuth 2. */ - API, + /** + * Allows anyone access, as long as they are logged in. + * + * Does not allow access from App Engine task-queues. + */ + AUTH_PUBLIC_LOGGED_IN( + ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), + AuthLevel.USER, + UserPolicy.PUBLIC), - /** Legacy authentication using cookie-based App Engine Users API. Must come last if present. */ - LEGACY + /** + * Allows only admins or App Engine task-queue access. + */ + AUTH_INTERNAL_OR_ADMIN( + ImmutableList.of(AuthMethod.INTERNAL, AuthMethod.API), + AuthLevel.APP, + UserPolicy.ADMIN), + + /** + * Allows only internal (App Engine task-queue) access. + */ + AUTH_INTERNAL_ONLY( + ImmutableList.of(AuthMethod.INTERNAL), + AuthLevel.APP, + UserPolicy.IGNORED); + + private final AuthSettings authSettings; + + Auth( + ImmutableList methods, + AuthLevel minimumLevel, + UserPolicy userPolicy) { + authSettings = AuthSettings.create(methods, minimumLevel, userPolicy); } - /** User authorization policy options. */ - public enum UserPolicy { - - /** This action ignores end users; the only configured auth method must be INTERNAL. */ - IGNORED, - - /** No user policy is enforced; anyone can access this action. */ - PUBLIC, - - /** - * If there is a user, it must be an admin, as determined by isUserAdmin(). - * - *

    Note that, according to App Engine, anybody with access to the app in the GCP Console, - * including editors and viewers, is an admin. - */ - ADMIN + public AuthSettings authSettings() { + return authSettings; } - - /** Enabled authentication methods for this action. */ - AuthMethod[] methods() default { AuthMethod.INTERNAL }; - - /** Required minimum level of authentication for this action. */ - AuthLevel minimumLevel() default AuthLevel.APP; - - /** Required user authorization policy for this action. */ - UserPolicy userPolicy() default UserPolicy.IGNORED; } diff --git a/java/google/registry/request/auth/RequestAuthenticator.java b/java/google/registry/request/auth/RequestAuthenticator.java index caf9ab16e..ec4332079 100644 --- a/java/google/registry/request/auth/RequestAuthenticator.java +++ b/java/google/registry/request/auth/RequestAuthenticator.java @@ -16,10 +16,12 @@ package google.registry.request.auth; import static com.google.common.base.Preconditions.checkArgument; +import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; +import com.google.errorprone.annotations.Immutable; import google.registry.util.FormattingLogger; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; @@ -44,6 +46,57 @@ public class RequestAuthenticator { this.legacyAuthenticationMechanism = legacyAuthenticationMechanism; } + /** + * Parameters used to configure the authenticator. + * + * AuthSettings shouldn't be used directly, instead - use one of the predefined {@link Auth} enum + * values. + */ + @Immutable + @AutoValue + public abstract static class AuthSettings { + + public abstract ImmutableList methods(); + public abstract AuthLevel minimumLevel(); + public abstract UserPolicy userPolicy(); + + static AuthSettings create( + ImmutableList methods, AuthLevel minimumLevel, UserPolicy userPolicy) { + return new AutoValue_RequestAuthenticator_AuthSettings(methods, minimumLevel, userPolicy); + } + } + + /** Available methods for authentication. */ + public enum AuthMethod { + + /** App Engine internal authentication. Must always be provided as the first method. */ + INTERNAL, + + /** Authentication methods suitable for API-style access, such as OAuth 2. */ + API, + + /** Legacy authentication using cookie-based App Engine Users API. Must come last if present. */ + LEGACY + } + + /** User authorization policy options. */ + public enum UserPolicy { + + /** This action ignores end users; the only configured auth method must be INTERNAL. */ + IGNORED, + + /** No user policy is enforced; anyone can access this action. */ + PUBLIC, + + /** + * If there is a user, it must be an admin, as determined by isUserAdmin(). + * + *

    Note that, according to App Engine, anybody with access to the app in the GCP Console, + * including editors and viewers, is an admin. + */ + ADMIN + } + /** * Attempts to authenticate and authorize the user, according to the settings of the action. * @@ -54,7 +107,7 @@ public class RequestAuthenticator { * not; authentication can be "successful" even without any authentication if the action's * auth settings are set to NONE -- in this case, NOT_AUTHENTICATED is returned */ - public Optional authorize(Auth auth, HttpServletRequest req) { + public Optional authorize(AuthSettings auth, HttpServletRequest req) { logger.infofmt("Action requires auth: %s", auth); AuthResult authResult = authenticate(auth, req); switch (auth.minimumLevel()) { @@ -104,15 +157,15 @@ public class RequestAuthenticator { * @param req the {@link HttpServletRequest}; some authentication mechanisms use HTTP headers * @return an authentication result; if no authentication was made, returns NOT_AUTHENTICATED */ - private AuthResult authenticate(Auth auth, HttpServletRequest req) { + private AuthResult authenticate(AuthSettings auth, HttpServletRequest req) { checkAuthConfig(auth); - for (Auth.AuthMethod authMethod : auth.methods()) { + for (AuthMethod authMethod : auth.methods()) { switch (authMethod) { // App Engine internal authentication, using the queue name header case INTERNAL: + // checkAuthConfig will have insured that the user policy is not USER. logger.info("Checking internal auth"); - // INTERNAL should be skipped if a user is required. - if (auth.minimumLevel() != AuthLevel.USER) { + { AuthResult authResult = appEngineInternalAuthenticationMechanism.authenticate(req); if (authResult.isAuthenticated()) { logger.infofmt("Authenticated: %s", authResult); @@ -148,25 +201,20 @@ public class RequestAuthenticator { return AuthResult.NOT_AUTHENTICATED; } - /** Validates an Auth object, checking for invalid setting combinations. */ - void checkAuthConfig(Auth auth) { - ImmutableList authMethods = ImmutableList.copyOf(auth.methods()); + /** Validates an AuthSettings object, checking for invalid setting combinations. */ + static void checkAuthConfig(AuthSettings auth) { + ImmutableList authMethods = ImmutableList.copyOf(auth.methods()); checkArgument(!authMethods.isEmpty(), "Must specify at least one auth method"); checkArgument( - Ordering.explicit(Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY) + Ordering.explicit(AuthMethod.INTERNAL, AuthMethod.API, AuthMethod.LEGACY) .isStrictlyOrdered(authMethods), "Auth methods must be unique and strictly in order - INTERNAL, API, LEGACY"); checkArgument( - authMethods.contains(Auth.AuthMethod.INTERNAL), - "Auth method INTERNAL must always be specified, and as the first auth method"); - if (authMethods.equals(ImmutableList.of(Auth.AuthMethod.INTERNAL))) { - checkArgument( - !auth.minimumLevel().equals(AuthLevel.USER), - "Actions with only INTERNAL auth may not require USER auth level"); - } else { - checkArgument( - !auth.userPolicy().equals(Auth.UserPolicy.IGNORED), - "Actions with auth methods beyond INTERNAL must not specify the IGNORED user policy"); - } + !(authMethods.contains(AuthMethod.INTERNAL) && auth.minimumLevel().equals(AuthLevel.USER)), + "Actions with INTERNAL auth method may not require USER auth level"); + checkArgument( + !(auth.userPolicy().equals(UserPolicy.IGNORED) + && !authMethods.equals(ImmutableList.of(AuthMethod.INTERNAL))), + "Actions with auth methods beyond INTERNAL must not specify the IGNORED user policy"); } } diff --git a/java/google/registry/tmch/BUILD b/java/google/registry/tmch/BUILD index 93a73fa78..22b63c96f 100644 --- a/java/google/registry/tmch/BUILD +++ b/java/google/registry/tmch/BUILD @@ -17,6 +17,7 @@ java_library( "//java/google/registry/keyring/api", "//java/google/registry/model", "//java/google/registry/request", + "//java/google/registry/request/auth", "//java/google/registry/util", "//java/google/registry/xml", "//third_party/java/objectify:objectify-v4_1", diff --git a/java/google/registry/tmch/NordnUploadAction.java b/java/google/registry/tmch/NordnUploadAction.java index e9ae67945..515e520b8 100644 --- a/java/google/registry/tmch/NordnUploadAction.java +++ b/java/google/registry/tmch/NordnUploadAction.java @@ -39,6 +39,7 @@ import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; +import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.UrlFetchException; @@ -57,7 +58,12 @@ import org.joda.time.Duration; * * @see NordnVerifyAction */ -@Action(path = NordnUploadAction.PATH, method = Action.Method.POST, automaticallyPrintOk = true) +@Action( + path = NordnUploadAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class NordnUploadAction implements Runnable { static final String PATH = "/_dr/task/nordnUpload"; diff --git a/java/google/registry/tmch/NordnVerifyAction.java b/java/google/registry/tmch/NordnVerifyAction.java index ec2a3e058..87805d51a 100644 --- a/java/google/registry/tmch/NordnVerifyAction.java +++ b/java/google/registry/tmch/NordnVerifyAction.java @@ -32,6 +32,7 @@ import google.registry.request.HttpException.ConflictException; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import google.registry.util.UrlFetchException; import java.io.IOException; @@ -51,7 +52,12 @@ import javax.inject.Inject; * @see * http://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-5.2.3.3 */ -@Action(path = NordnVerifyAction.PATH, method = Action.Method.POST, automaticallyPrintOk = true) +@Action( + path = NordnVerifyAction.PATH, + method = Action.Method.POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class NordnVerifyAction implements Runnable { public static final String PARAM_CSV_DATA = "csvData"; diff --git a/java/google/registry/tmch/TmchCrlAction.java b/java/google/registry/tmch/TmchCrlAction.java index d4d991565..4f47fc8fd 100644 --- a/java/google/registry/tmch/TmchCrlAction.java +++ b/java/google/registry/tmch/TmchCrlAction.java @@ -20,13 +20,19 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Optional; import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; +import google.registry.request.auth.Auth; import java.io.IOException; import java.net.URL; import java.security.GeneralSecurityException; import javax.inject.Inject; /** Action to download the latest ICANN TMCH CRL from MarksDB. */ -@Action(path = "/_dr/task/tmchCrl", method = POST, automaticallyPrintOk = true) +@Action( + path = "/_dr/task/tmchCrl", + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class TmchCrlAction implements Runnable { @Inject Marksdb marksdb; diff --git a/java/google/registry/tmch/TmchDnlAction.java b/java/google/registry/tmch/TmchDnlAction.java index 664c4918e..102cfd1b3 100644 --- a/java/google/registry/tmch/TmchDnlAction.java +++ b/java/google/registry/tmch/TmchDnlAction.java @@ -20,6 +20,7 @@ import com.google.common.base.Optional; import google.registry.keyring.api.KeyModule.Key; import google.registry.model.tmch.ClaimsListShard; import google.registry.request.Action; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.security.SignatureException; @@ -28,7 +29,12 @@ import javax.inject.Inject; import org.bouncycastle.openpgp.PGPException; /** Action to download the latest domain name list (aka claims list) from MarksDB. */ -@Action(path = "/_dr/task/tmchDnl", method = POST, automaticallyPrintOk = true) +@Action( + path = "/_dr/task/tmchDnl", + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class TmchDnlAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/tmch/TmchSmdrlAction.java b/java/google/registry/tmch/TmchSmdrlAction.java index 57620b861..c024f56c9 100644 --- a/java/google/registry/tmch/TmchSmdrlAction.java +++ b/java/google/registry/tmch/TmchSmdrlAction.java @@ -20,6 +20,7 @@ import com.google.common.base.Optional; import google.registry.keyring.api.KeyModule.Key; import google.registry.model.smd.SignedMarkRevocationList; import google.registry.request.Action; +import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; import java.io.IOException; import java.security.SignatureException; @@ -28,7 +29,12 @@ import javax.inject.Inject; import org.bouncycastle.openpgp.PGPException; /** Action to download the latest signed mark revocation list from MarksDB. */ -@Action(path = "/_dr/task/tmchSmdrl", method = POST, automaticallyPrintOk = true) +@Action( + path = "/_dr/task/tmchSmdrl", + method = POST, + automaticallyPrintOk = true, + auth = Auth.AUTH_INTERNAL_ONLY +) public final class TmchSmdrlAction implements Runnable { private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); diff --git a/java/google/registry/tools/server/CreateGroupsAction.java b/java/google/registry/tools/server/CreateGroupsAction.java index 5eb01dcda..9813f1635 100644 --- a/java/google/registry/tools/server/CreateGroupsAction.java +++ b/java/google/registry/tools/server/CreateGroupsAction.java @@ -33,7 +33,6 @@ import google.registry.request.HttpException.InternalServerErrorException; import google.registry.request.Parameter; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Concurrent; import google.registry.util.FormattingLogger; import java.io.PrintWriter; @@ -46,12 +45,7 @@ import javax.inject.Inject; @Action( path = CreateGroupsAction.PATH, method = POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class CreateGroupsAction implements Runnable { diff --git a/java/google/registry/tools/server/CreatePremiumListAction.java b/java/google/registry/tools/server/CreatePremiumListAction.java index a819ac0e0..584ea54d7 100644 --- a/java/google/registry/tools/server/CreatePremiumListAction.java +++ b/java/google/registry/tools/server/CreatePremiumListAction.java @@ -26,7 +26,6 @@ import google.registry.model.registry.label.PremiumList; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import java.util.List; import javax.inject.Inject; @@ -37,12 +36,7 @@ import javax.inject.Inject; @Action( path = CreatePremiumListAction.PATH, method = POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction { diff --git a/java/google/registry/tools/server/DeleteEntityAction.java b/java/google/registry/tools/server/DeleteEntityAction.java index b61790f1e..485bc34d0 100644 --- a/java/google/registry/tools/server/DeleteEntityAction.java +++ b/java/google/registry/tools/server/DeleteEntityAction.java @@ -32,7 +32,6 @@ import google.registry.request.HttpException.BadRequestException; import google.registry.request.Parameter; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import javax.inject.Inject; @@ -51,12 +50,7 @@ import javax.inject.Inject; */ @Action( path = DeleteEntityAction.PATH, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class DeleteEntityAction implements Runnable { diff --git a/java/google/registry/tools/server/GenerateZoneFilesAction.java b/java/google/registry/tools/server/GenerateZoneFilesAction.java index 584b3e7e5..69d402ac2 100644 --- a/java/google/registry/tools/server/GenerateZoneFilesAction.java +++ b/java/google/registry/tools/server/GenerateZoneFilesAction.java @@ -48,7 +48,6 @@ import google.registry.request.Action; import google.registry.request.HttpException.BadRequestException; import google.registry.request.JsonActionRunner; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import java.io.IOException; import java.io.OutputStream; @@ -72,14 +71,9 @@ import org.joda.time.Duration; * 29 days in the past, and must be at midnight UTC. */ @Action( - path = GenerateZoneFilesAction.PATH, - method = POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + path = GenerateZoneFilesAction.PATH, + method = POST, + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class GenerateZoneFilesAction implements Runnable, JsonActionRunner.JsonAction { diff --git a/java/google/registry/tools/server/KillAllCommitLogsAction.java b/java/google/registry/tools/server/KillAllCommitLogsAction.java index 9012a8d51..7f7decb82 100644 --- a/java/google/registry/tools/server/KillAllCommitLogsAction.java +++ b/java/google/registry/tools/server/KillAllCommitLogsAction.java @@ -32,6 +32,7 @@ import google.registry.model.ofy.CommitLogBucket; import google.registry.model.ofy.CommitLogCheckpointRoot; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import java.util.Arrays; import javax.inject.Inject; @@ -43,7 +44,11 @@ import javax.inject.Inject; * which only admin users can do. That makes this command hard to use, which is appropriate, given * the drastic consequences of accidental execution. */ -@Action(path = "/_dr/task/killAllCommitLogs", method = POST) +@Action( + path = "/_dr/task/killAllCommitLogs", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class KillAllCommitLogsAction implements Runnable { @Inject MapreduceRunner mrRunner; diff --git a/java/google/registry/tools/server/KillAllEppResourcesAction.java b/java/google/registry/tools/server/KillAllEppResourcesAction.java index 36a08f0c7..480f05970 100644 --- a/java/google/registry/tools/server/KillAllEppResourcesAction.java +++ b/java/google/registry/tools/server/KillAllEppResourcesAction.java @@ -32,6 +32,7 @@ import google.registry.model.index.EppResourceIndex; import google.registry.model.index.ForeignKeyIndex; import google.registry.request.Action; import google.registry.request.Response; +import google.registry.request.auth.Auth; import javax.inject.Inject; /** @@ -42,7 +43,11 @@ import javax.inject.Inject; * which only admin users can do. That makes this command hard to use, which is appropriate, given * the drastic consequences of accidental execution. */ -@Action(path = "/_dr/task/killAllEppResources", method = POST) +@Action( + path = "/_dr/task/killAllEppResources", + method = POST, + auth = Auth.AUTH_INTERNAL_ONLY +) public class KillAllEppResourcesAction implements Runnable { @Inject MapreduceRunner mrRunner; diff --git a/java/google/registry/tools/server/ListDomainsAction.java b/java/google/registry/tools/server/ListDomainsAction.java index b2564d688..f35c08a41 100644 --- a/java/google/registry/tools/server/ListDomainsAction.java +++ b/java/google/registry/tools/server/ListDomainsAction.java @@ -27,7 +27,6 @@ import google.registry.model.domain.DomainResource; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import java.util.Comparator; import java.util.List; @@ -37,12 +36,7 @@ import javax.inject.Inject; @Action( path = ListDomainsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListDomainsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/ListHostsAction.java b/java/google/registry/tools/server/ListHostsAction.java index ef8102d0c..3e904abdb 100644 --- a/java/google/registry/tools/server/ListHostsAction.java +++ b/java/google/registry/tools/server/ListHostsAction.java @@ -25,7 +25,6 @@ import google.registry.model.EppResourceUtils; import google.registry.model.host.HostResource; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import java.util.Comparator; import javax.inject.Inject; @@ -35,12 +34,7 @@ import org.joda.time.DateTime; @Action( path = ListHostsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListHostsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/ListPremiumListsAction.java b/java/google/registry/tools/server/ListPremiumListsAction.java index caeff6b61..7127d72aa 100644 --- a/java/google/registry/tools/server/ListPremiumListsAction.java +++ b/java/google/registry/tools/server/ListPremiumListsAction.java @@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.model.registry.label.PremiumList; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** @@ -32,12 +31,7 @@ import javax.inject.Inject; @Action( path = ListPremiumListsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListPremiumListsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/ListRegistrarsAction.java b/java/google/registry/tools/server/ListRegistrarsAction.java index 156add7cb..be99bfaa0 100644 --- a/java/google/registry/tools/server/ListRegistrarsAction.java +++ b/java/google/registry/tools/server/ListRegistrarsAction.java @@ -23,19 +23,13 @@ import com.google.common.collect.ImmutableSet; import google.registry.model.registrar.Registrar; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** An action that lists registrars, for use by the {@code nomulus list_registrars} command. */ @Action( path = ListRegistrarsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListRegistrarsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/ListReservedListsAction.java b/java/google/registry/tools/server/ListReservedListsAction.java index deb0e6eed..3a1b3030c 100644 --- a/java/google/registry/tools/server/ListReservedListsAction.java +++ b/java/google/registry/tools/server/ListReservedListsAction.java @@ -23,19 +23,13 @@ import com.google.common.collect.ImmutableSet; import google.registry.model.registry.label.ReservedList; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** A that lists reserved lists, for use by the {@code nomulus list_reserved_lists} command. */ @Action( path = ListReservedListsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListReservedListsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/ListTldsAction.java b/java/google/registry/tools/server/ListTldsAction.java index e9fe81254..4c85c4ec3 100644 --- a/java/google/registry/tools/server/ListTldsAction.java +++ b/java/google/registry/tools/server/ListTldsAction.java @@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableSet; import google.registry.model.registry.Registry; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import javax.inject.Inject; import org.joda.time.DateTime; @@ -35,12 +34,7 @@ import org.joda.time.DateTime; @Action( path = ListTldsAction.PATH, method = {GET, POST}, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public final class ListTldsAction extends ListObjectsAction { diff --git a/java/google/registry/tools/server/RefreshDnsForAllDomainsAction.java b/java/google/registry/tools/server/RefreshDnsForAllDomainsAction.java index a2d3e1f5f..39dfbcc30 100644 --- a/java/google/registry/tools/server/RefreshDnsForAllDomainsAction.java +++ b/java/google/registry/tools/server/RefreshDnsForAllDomainsAction.java @@ -31,7 +31,6 @@ import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; import javax.inject.Inject; @@ -51,12 +50,7 @@ import org.joda.time.DateTimeZone; */ @Action( path = "/_dr/task/refreshDnsForAllDomains", - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class RefreshDnsForAllDomainsAction implements Runnable { diff --git a/java/google/registry/tools/server/ResaveAllEppResourcesAction.java b/java/google/registry/tools/server/ResaveAllEppResourcesAction.java index 841329f47..e30dc3bdf 100644 --- a/java/google/registry/tools/server/ResaveAllEppResourcesAction.java +++ b/java/google/registry/tools/server/ResaveAllEppResourcesAction.java @@ -27,7 +27,6 @@ import google.registry.model.EppResource; import google.registry.request.Action; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import javax.inject.Inject; /** @@ -43,12 +42,7 @@ import javax.inject.Inject; */ @Action( path = "/_dr/task/resaveAllEppResources", - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class ResaveAllEppResourcesAction implements Runnable { diff --git a/java/google/registry/tools/server/UpdatePremiumListAction.java b/java/google/registry/tools/server/UpdatePremiumListAction.java index de732ee37..ec550e085 100644 --- a/java/google/registry/tools/server/UpdatePremiumListAction.java +++ b/java/google/registry/tools/server/UpdatePremiumListAction.java @@ -24,7 +24,6 @@ import com.google.common.collect.ImmutableMap; import google.registry.model.registry.label.PremiumList; import google.registry.request.Action; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import java.util.List; import javax.inject.Inject; @@ -35,12 +34,7 @@ import javax.inject.Inject; @Action( path = UpdatePremiumListAction.PATH, method = POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction { diff --git a/java/google/registry/tools/server/VerifyOteAction.java b/java/google/registry/tools/server/VerifyOteAction.java index 29fa0ed9c..22437a925 100644 --- a/java/google/registry/tools/server/VerifyOteAction.java +++ b/java/google/registry/tools/server/VerifyOteAction.java @@ -47,7 +47,6 @@ import google.registry.request.Action; import google.registry.request.JsonActionRunner; import google.registry.request.JsonActionRunner.JsonAction; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -62,12 +61,7 @@ import javax.inject.Inject; @Action( path = VerifyOteAction.PATH, method = Action.Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class VerifyOteAction implements Runnable, JsonAction { diff --git a/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/java/google/registry/ui/server/registrar/ConsoleUiAction.java index 4b26ab9db..0a6d8f85a 100644 --- a/java/google/registry/ui/server/registrar/ConsoleUiAction.java +++ b/java/google/registry/ui/server/registrar/ConsoleUiAction.java @@ -34,7 +34,6 @@ import google.registry.model.registrar.Registrar; import google.registry.request.Action; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; import google.registry.security.XsrfTokenManager; import google.registry.ui.server.SoyTemplateUtils; @@ -45,12 +44,7 @@ import javax.servlet.http.HttpServletRequest; /** Action that serves Registrar Console single HTML page (SPA). */ @Action( path = ConsoleUiAction.PATH, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.NONE, - userPolicy = Auth.UserPolicy.PUBLIC - ) + auth = Auth.AUTH_PUBLIC ) public final class ConsoleUiAction implements Runnable { diff --git a/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java b/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java index c3da31834..a7becab86 100644 --- a/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java +++ b/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java @@ -36,7 +36,6 @@ import google.registry.request.Action; import google.registry.request.JsonActionRunner; import google.registry.request.JsonActionRunner.JsonAction; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; import google.registry.security.JsonResponseHelper; import google.registry.ui.forms.FormField; @@ -97,12 +96,7 @@ import org.joda.money.Money; @Action( path = "/registrar-payment", method = Action.Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC - ) + auth = Auth.AUTH_PUBLIC_LOGGED_IN ) public final class RegistrarPaymentAction implements Runnable, JsonAction { diff --git a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java b/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java index 41cd2448b..a3dda2ad9 100644 --- a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java +++ b/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java @@ -29,7 +29,6 @@ import google.registry.request.Action; import google.registry.request.JsonActionRunner; import google.registry.request.JsonActionRunner.JsonAction; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; import google.registry.security.JsonResponseHelper; import java.util.Map; @@ -72,12 +71,7 @@ import org.joda.money.CurrencyUnit; @Action( path = "/registrar-payment-setup", method = Action.Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC - ) + auth = Auth.AUTH_PUBLIC_LOGGED_IN ) public final class RegistrarPaymentSetupAction implements Runnable, JsonAction { diff --git a/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java b/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java index 5477e7beb..c9ab29529 100644 --- a/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java +++ b/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java @@ -41,7 +41,6 @@ import google.registry.request.Action; import google.registry.request.HttpException.BadRequestException; import google.registry.request.JsonActionRunner; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; import google.registry.security.JsonResponseHelper; import google.registry.ui.forms.FormException; @@ -65,12 +64,7 @@ import javax.servlet.http.HttpServletRequest; @Action( path = RegistrarSettingsAction.PATH, method = Action.Method.POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC - ) + auth = Auth.AUTH_PUBLIC_LOGGED_IN ) public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonAction { diff --git a/java/google/registry/whois/WhoisHttpServer.java b/java/google/registry/whois/WhoisHttpServer.java index fce8fd2a8..397c425c1 100644 --- a/java/google/registry/whois/WhoisHttpServer.java +++ b/java/google/registry/whois/WhoisHttpServer.java @@ -33,7 +33,6 @@ import google.registry.request.Action; import google.registry.request.RequestPath; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.whois.WhoisMetrics.WhoisMetric; @@ -99,7 +98,7 @@ import org.joda.time.Duration; @Action( path = WhoisHttpServer.PATH, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE, userPolicy = Auth.UserPolicy.PUBLIC) + auth = Auth.AUTH_PUBLIC_ANONYMOUS ) public final class WhoisHttpServer implements Runnable { diff --git a/java/google/registry/whois/WhoisServer.java b/java/google/registry/whois/WhoisServer.java index edc050091..100b39a1a 100644 --- a/java/google/registry/whois/WhoisServer.java +++ b/java/google/registry/whois/WhoisServer.java @@ -25,7 +25,6 @@ import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; import google.registry.request.Response; import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthLevel; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; @@ -54,12 +53,7 @@ import org.joda.time.DateTime; @Action( path = "/_dr/whois", method = POST, - auth = - @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.APP, - userPolicy = Auth.UserPolicy.ADMIN - ) + auth = Auth.AUTH_INTERNAL_OR_ADMIN ) public class WhoisServer implements Runnable { diff --git a/javatests/google/registry/module/frontend/testdata/frontend_routing.txt b/javatests/google/registry/module/frontend/testdata/frontend_routing.txt index 51acb232b..37cf14f0e 100644 --- a/javatests/google/registry/module/frontend/testdata/frontend_routing.txt +++ b/javatests/google/registry/module/frontend/testdata/frontend_routing.txt @@ -12,8 +12,8 @@ PATH CLASS METHODS OK AUTH_METHODS /rdap/nameserver/(*) RdapNameserverAction GET,HEAD n INTERNAL NONE PUBLIC /rdap/nameservers RdapNameserverSearchAction GET,HEAD n INTERNAL NONE PUBLIC /registrar ConsoleUiAction GET n INTERNAL,API,LEGACY NONE PUBLIC -/registrar-payment RegistrarPaymentAction POST n INTERNAL,API,LEGACY USER PUBLIC -/registrar-payment-setup RegistrarPaymentSetupAction POST n INTERNAL,API,LEGACY USER PUBLIC -/registrar-settings RegistrarSettingsAction POST n INTERNAL,API,LEGACY USER PUBLIC -/registrar-xhr EppConsoleAction POST n INTERNAL,API,LEGACY USER PUBLIC +/registrar-payment RegistrarPaymentAction POST n API,LEGACY USER PUBLIC +/registrar-payment-setup RegistrarPaymentSetupAction POST n API,LEGACY USER PUBLIC +/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC +/registrar-xhr EppConsoleAction POST n API,LEGACY USER PUBLIC /whois/(*) WhoisHttpServer GET n INTERNAL NONE PUBLIC diff --git a/javatests/google/registry/request/RequestHandlerTest.java b/javatests/google/registry/request/RequestHandlerTest.java index e47af9eee..23f6028ac 100644 --- a/javatests/google/registry/request/RequestHandlerTest.java +++ b/javatests/google/registry/request/RequestHandlerTest.java @@ -17,30 +17,23 @@ package google.registry.request; import static com.google.common.truth.Truth.assertThat; import static google.registry.request.Action.Method.GET; import static google.registry.request.Action.Method.POST; +import static google.registry.request.auth.Auth.AUTH_INTERNAL_OR_ADMIN; +import static google.registry.request.auth.Auth.AUTH_PUBLIC; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; -import com.google.appengine.api.oauth.OAuthServiceFactory; import com.google.appengine.api.users.User; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; +import com.google.common.base.Optional; import com.google.common.testing.NullPointerTester; import google.registry.request.HttpException.ServiceUnavailableException; -import google.registry.request.auth.AppEngineInternalAuthenticationMechanism; -import google.registry.request.auth.Auth; import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; -import google.registry.request.auth.AuthenticationMechanism; -import google.registry.request.auth.LegacyAuthenticationMechanism; -import google.registry.request.auth.OAuthAuthenticationMechanism; import google.registry.request.auth.RequestAuthenticator; -import google.registry.security.XsrfTokenManager; +import google.registry.request.auth.UserAuthInfo; import google.registry.testing.AppEngineRule; -import google.registry.testing.FakeClock; -import google.registry.testing.FakeUserService; import google.registry.testing.Providers; import google.registry.testing.UserInfo; import java.io.PrintWriter; @@ -69,7 +62,7 @@ public final class RequestHandlerTest { path = "/bumblebee", method = {GET, POST}, isPrefix = true, - auth = @Auth(minimumLevel = AuthLevel.NONE) + auth = AUTH_PUBLIC ) public static class BumblebeeTask implements Runnable { @Override @@ -80,7 +73,7 @@ public final class RequestHandlerTest { path = "/sloth", method = POST, automaticallyPrintOk = true, - auth = @Auth(minimumLevel = AuthLevel.NONE) + auth = AUTH_PUBLIC ) public static class SlothTask implements Runnable { @Override @@ -90,14 +83,14 @@ public final class RequestHandlerTest { @Action( path = "/safe-sloth", method = {GET, POST}, - auth = @Auth(minimumLevel = AuthLevel.NONE) + auth = AUTH_PUBLIC ) public static class SafeSlothTask implements Runnable { @Override public void run() {} } - @Action(path = "/fail", auth = @Auth(minimumLevel = AuthLevel.NONE)) + @Action(path = "/fail", auth = AUTH_PUBLIC) public static final class FailTask implements Runnable { @Override public void run() { @@ -105,7 +98,7 @@ public final class RequestHandlerTest { } } - @Action(path = "/failAtConstruction", auth = @Auth(minimumLevel = AuthLevel.NONE)) + @Action(path = "/failAtConstruction", auth = AUTH_PUBLIC) public static final class FailAtConstructionTask implements Runnable { public FailAtConstructionTask() { throw new ServiceUnavailableException("Fail at construction"); @@ -132,7 +125,7 @@ public final class RequestHandlerTest { @Action( path = "/auth/none", - auth = @Auth(minimumLevel = AuthLevel.NONE), + auth = AUTH_PUBLIC, method = Action.Method.GET ) public class AuthNoneAction extends AuthBase { @@ -142,14 +135,11 @@ public final class RequestHandlerTest { } @Action( - path = "/auth/adminUserAnyMethod", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.ADMIN), + path = "/auth/adminUser", + auth = AUTH_INTERNAL_OR_ADMIN, method = Action.Method.GET) - public class AuthAdminUserAnyMethodAction extends AuthBase { - AuthAdminUserAnyMethodAction(AuthResult authResult) { + public class AuthAdminUserAction extends AuthBase { + AuthAdminUserAction(AuthResult authResult) { super(authResult); } } @@ -190,8 +180,8 @@ public final class RequestHandlerTest { return new AuthNoneAction(component.getRequestModule().provideAuthResult()); } - public AuthAdminUserAnyMethodAction authAdminUserAnyMethodAction() { - return new AuthAdminUserAnyMethodAction(component.getRequestModule().provideAuthResult()); + public AuthAdminUserAction authAdminUserAction() { + return new AuthAdminUserAction(component.getRequestModule().provideAuthResult()); } } @@ -209,30 +199,16 @@ public final class RequestHandlerTest { private final BumblebeeTask bumblebeeTask = mock(BumblebeeTask.class); private final SlothTask slothTask = mock(SlothTask.class); private final SafeSlothTask safeSlothTask = mock(SafeSlothTask.class); + private final RequestAuthenticator requestAuthenticator = mock(RequestAuthenticator.class); private final Component component = new Component(); private final StringWriter httpOutput = new StringWriter(); private RequestHandler handler; private AuthResult providedAuthResult = null; private final User testUser = new User("test@example.com", "test@example.com"); - private RequestAuthenticator requestAuthenticator; - private XsrfTokenManager xsrfTokenManager; - private FakeUserService userService; @Before public void before() throws Exception { - userService = new FakeUserService(); - xsrfTokenManager = new XsrfTokenManager(new FakeClock(), userService); - requestAuthenticator = new RequestAuthenticator( - new AppEngineInternalAuthenticationMechanism(), - ImmutableList.of( - new OAuthAuthenticationMechanism( - OAuthServiceFactory.getOAuthService(), - ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email"), - ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email"), - ImmutableSet.of("proxy-client-id", "regtool-client-id"))), - new LegacyAuthenticationMechanism(userService, xsrfTokenManager)); - // Initialize here, not inline, so that we pick up the mocked UserService. handler = RequestHandler.createForTest( Component.class, @@ -256,19 +232,24 @@ public final class RequestHandlerTest { public void testHandleRequest_normalRequest_works() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/bumblebee"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verifyZeroInteractions(rsp); verify(bumblebeeTask).run(); } @Test public void testHandleRequest_multipleMethodMappings_works() throws Exception { - userService.setUser(testUser, false); when(req.getMethod()).thenReturn("POST"); - when(req.getHeader("X-CSRF-Token")) - .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail())); when(req.getRequestURI()).thenReturn("/bumblebee"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(bumblebeeTask).run(); } @@ -276,18 +257,23 @@ public final class RequestHandlerTest { public void testHandleRequest_prefixEnabled_subpathsWork() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/bumblebee/hive"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(bumblebeeTask).run(); } @Test public void testHandleRequest_taskHasAutoPrintOk_printsOk() throws Exception { - userService.setUser(testUser, false); when(req.getMethod()).thenReturn("POST"); - when(req.getHeader("X-CSRF-Token")) - .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail())); when(req.getRequestURI()).thenReturn("/sloth"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(slothTask).run(); verify(rsp).setContentType("text/plain; charset=utf-8"); verify(rsp).getWriter(); @@ -298,7 +284,11 @@ public final class RequestHandlerTest { public void testHandleRequest_prefixDisabled_subpathsReturn404NotFound() throws Exception { when(req.getMethod()).thenReturn("POST"); when(req.getRequestURI()).thenReturn("/sloth/nest"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(404); } @@ -306,7 +296,11 @@ public final class RequestHandlerTest { public void testHandleRequest_taskThrowsHttpException_getsHandledByHandler() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/fail"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(503, "Set sail for fail"); } @@ -316,7 +310,11 @@ public final class RequestHandlerTest { throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/failAtConstruction"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(503, "Fail at construction"); } @@ -324,7 +322,11 @@ public final class RequestHandlerTest { public void testHandleRequest_notFound_returns404NotFound() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/bogus"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(404); } @@ -332,7 +334,11 @@ public final class RequestHandlerTest { public void testHandleRequest_methodNotAllowed_returns405MethodNotAllowed() throws Exception { when(req.getMethod()).thenReturn("POST"); when(req.getRequestURI()).thenReturn("/fail"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(405); } @@ -340,7 +346,11 @@ public final class RequestHandlerTest { public void testHandleRequest_insaneMethod_returns405MethodNotAllowed() throws Exception { when(req.getMethod()).thenReturn("FIREAWAY"); when(req.getRequestURI()).thenReturn("/fail"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(405); } @@ -350,7 +360,11 @@ public final class RequestHandlerTest { public void testHandleRequest_lowercaseMethod_notRecognized() throws Exception { when(req.getMethod()).thenReturn("get"); when(req.getRequestURI()).thenReturn("/bumblebee"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(rsp).sendError(405); } @@ -359,19 +373,19 @@ public final class RequestHandlerTest { NullPointerTester tester = new NullPointerTester(); tester.setDefault(Class.class, Component.class); tester.setDefault(RequestAuthenticator.class, requestAuthenticator); - tester.setDefault(XsrfTokenManager.class, xsrfTokenManager); tester.testAllPublicStaticMethods(RequestHandler.class); tester.testAllPublicInstanceMethods(handler); } @Test public void testXsrfProtection_validTokenProvided_runsAction() throws Exception { - userService.setUser(testUser, false); when(req.getMethod()).thenReturn("POST"); - when(req.getHeader("X-CSRF-Token")) - .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail())); when(req.getRequestURI()).thenReturn("/safe-sloth"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(safeSlothTask).run(); } @@ -379,7 +393,11 @@ public final class RequestHandlerTest { public void testXsrfProtection_GETMethodWithoutToken_doesntCheckToken() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/safe-sloth"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); + handler.handleRequest(req, rsp); + verify(safeSlothTask).run(); } @@ -387,6 +405,8 @@ public final class RequestHandlerTest { public void testNoAuthNeeded_success() throws Exception { when(req.getMethod()).thenReturn("GET"); when(req.getRequestURI()).thenReturn("/auth/none"); + when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req)) + .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE))); handler.handleRequest(req, rsp); @@ -396,22 +416,11 @@ public final class RequestHandlerTest { } @Test - public void testAuthNeeded_notLoggedIn() throws Exception { + public void testAuthNeeded_failure() throws Exception { when(req.getMethod()).thenReturn("GET"); - when(req.getRequestURI()).thenReturn("/auth/adminUserAnyMethod"); - - handler.handleRequest(req, rsp); - - verify(rsp).sendError(403, "Not authorized"); - assertThat(providedAuthResult).isNull(); - assertThat(providedAuthResult).isNull(); - } - - @Test - public void testAuthNeeded_notAuthorized() throws Exception { - userService.setUser(testUser, false); - when(req.getMethod()).thenReturn("GET"); - when(req.getRequestURI()).thenReturn("/auth/adminUserAnyMethod"); + when(req.getRequestURI()).thenReturn("/auth/adminUser"); + when(requestAuthenticator.authorize(AUTH_INTERNAL_OR_ADMIN.authSettings(), req)) + .thenReturn(Optional.absent()); handler.handleRequest(req, rsp); @@ -421,9 +430,11 @@ public final class RequestHandlerTest { @Test public void testAuthNeeded_success() throws Exception { - userService.setUser(testUser, true); when(req.getMethod()).thenReturn("GET"); - when(req.getRequestURI()).thenReturn("/auth/adminUserAnyMethod"); + when(req.getRequestURI()).thenReturn("/auth/adminUser"); + when(requestAuthenticator.authorize(AUTH_INTERNAL_OR_ADMIN.authSettings(), req)) + .thenReturn( + Optional.of(AuthResult.create(AuthLevel.USER, UserAuthInfo.create(testUser, true)))); handler.handleRequest(req, rsp); @@ -433,4 +444,5 @@ public final class RequestHandlerTest { assertThat(providedAuthResult.userAuthInfo().get().user()).isEqualTo(testUser); assertThat(providedAuthResult.userAuthInfo().get().oauthTokenInfo()).isAbsent(); } + } diff --git a/javatests/google/registry/request/RouterTest.java b/javatests/google/registry/request/RouterTest.java index bf284da44..2b9c870bf 100644 --- a/javatests/google/registry/request/RouterTest.java +++ b/javatests/google/registry/request/RouterTest.java @@ -15,6 +15,7 @@ package google.registry.request; import static com.google.common.truth.Truth.assertThat; +import static google.registry.request.auth.Auth.AUTH_INTERNAL_ONLY; import com.google.common.base.Function; import com.google.common.base.Optional; @@ -46,7 +47,7 @@ public final class RouterTest { //////////////////////////////////////////////////////////////////////////////////////////////// - @Action(path = "/sloth") + @Action(path = "/sloth", auth = AUTH_INTERNAL_ONLY) public static final class SlothTask implements Runnable { @Override public void run() {} @@ -76,7 +77,7 @@ public final class RouterTest { //////////////////////////////////////////////////////////////////////////////////////////////// - @Action(path = "/prefix", isPrefix = true) + @Action(path = "/prefix", isPrefix = true, auth = AUTH_INTERNAL_ONLY) public static final class PrefixTask implements Runnable { @Override public void run() {} @@ -102,7 +103,7 @@ public final class RouterTest { //////////////////////////////////////////////////////////////////////////////////////////////// - @Action(path = "/prefix/long", isPrefix = true) + @Action(path = "/prefix/long", isPrefix = true, auth = AUTH_INTERNAL_ONLY) public static final class LongTask implements Runnable { @Override public void run() {} @@ -151,13 +152,13 @@ public final class RouterTest { //////////////////////////////////////////////////////////////////////////////////////////////// - @Action(path = "/samePathAsOtherTask") + @Action(path = "/samePathAsOtherTask", auth = AUTH_INTERNAL_ONLY) public static final class DuplicateTask1 implements Runnable { @Override public void run() {} } - @Action(path = "/samePathAsOtherTask") + @Action(path = "/samePathAsOtherTask", auth = AUTH_INTERNAL_ONLY) public static final class DuplicateTask2 implements Runnable { @Override public void run() {} diff --git a/javatests/google/registry/request/auth/AuthTest.java b/javatests/google/registry/request/auth/AuthTest.java new file mode 100644 index 000000000..e36902990 --- /dev/null +++ b/javatests/google/registry/request/auth/AuthTest.java @@ -0,0 +1,31 @@ +// Copyright 2017 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.request.auth; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Auth}. */ +@RunWith(JUnit4.class) +public final class AuthTest { + + @Test + public void testAuthValues_validConfig() throws Exception { + for (Auth auth : Auth.values()) { + RequestAuthenticator.checkAuthConfig(auth.authSettings()); + } + } +} diff --git a/javatests/google/registry/request/auth/RequestAuthenticatorTest.java b/javatests/google/registry/request/auth/RequestAuthenticatorTest.java index 799825b94..86771f4fa 100644 --- a/javatests/google/registry/request/auth/RequestAuthenticatorTest.java +++ b/javatests/google/registry/request/auth/RequestAuthenticatorTest.java @@ -25,7 +25,9 @@ import com.google.appengine.api.users.UserService; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import google.registry.request.Action; +import google.registry.request.auth.RequestAuthenticator.AuthMethod; +import google.registry.request.auth.RequestAuthenticator.AuthSettings; +import google.registry.request.auth.RequestAuthenticator.UserPolicy; import google.registry.security.XsrfTokenManager; import google.registry.testing.AppEngineRule; import google.registry.testing.ExceptionRule; @@ -49,79 +51,55 @@ public class RequestAuthenticatorTest { @Rule public final ExceptionRule thrown = new ExceptionRule(); - @Action( - path = "/auth/none", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL}, - minimumLevel = AuthLevel.NONE, - userPolicy = Auth.UserPolicy.IGNORED), - method = Action.Method.GET) - public static class AuthNone {} + private static final AuthSettings AUTH_NONE = AuthSettings.create( + ImmutableList.of(AuthMethod.INTERNAL), + AuthLevel.NONE, + UserPolicy.IGNORED); - @Action( - path = "/auth/internalOnly", - auth = @Auth(minimumLevel = AuthLevel.APP), - method = Action.Method.GET) - public static class AuthInternalOnly {} + private static final AuthSettings AUTH_INTERNAL_ONLY = AuthSettings.create( + ImmutableList.of(AuthMethod.INTERNAL), + AuthLevel.APP, + UserPolicy.IGNORED); - @Action( - path = "/auth/anyUserAnyMethod", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC), - method = Action.Method.GET) - public static class AuthAnyUserAnyMethod {} + private static final AuthSettings AUTH_ANY_USER_ANY_METHOD = AuthSettings.create( + ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), + AuthLevel.USER, + UserPolicy.PUBLIC); - @Action( - path = "/auth/anyUserNoLegacy", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.PUBLIC), - method = Action.Method.GET) - public static class AuthAnyUserNoLegacy {} + private static final AuthSettings AUTH_ANY_USER_NO_LEGACY = AuthSettings.create( + ImmutableList.of(AuthMethod.API), + AuthLevel.USER, + UserPolicy.PUBLIC); - @Action( - path = "/auth/adminUserAnyMethod", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}, - minimumLevel = AuthLevel.USER, - userPolicy = Auth.UserPolicy.ADMIN), - method = Action.Method.GET) - public static class AuthAdminUserAnyMethod {} + private static final AuthSettings AUTH_ADMIN_USER_ANY_METHOD = AuthSettings.create( + ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), + AuthLevel.USER, + UserPolicy.ADMIN); - @Action( - path = "/auth/noMethods", - auth = @Auth(methods = {})) - public static class AuthNoMethods {} + private static final AuthSettings AUTH_NO_METHODS = AuthSettings.create( + ImmutableList.of(), + AuthLevel.APP, + UserPolicy.IGNORED); - @Action( - path = "/auth/missingInternal", - auth = @Auth(methods = {Auth.AuthMethod.API, Auth.AuthMethod.LEGACY})) - public static class AuthMissingInternal {} + private static final AuthSettings AUTH_WRONG_METHOD_ORDERING = AuthSettings.create( + ImmutableList.of(AuthMethod.API, AuthMethod.INTERNAL), + AuthLevel.APP, + UserPolicy.IGNORED); - @Action( - path = "/auth/wrongMethodOrdering", - auth = @Auth(methods = {Auth.AuthMethod.API, Auth.AuthMethod.INTERNAL})) - public static class AuthWrongMethodOrdering {} + private static final AuthSettings AUTH_DUPLICATE_METHODS = AuthSettings.create( + ImmutableList.of(AuthMethod.INTERNAL, AuthMethod.API, AuthMethod.API), + AuthLevel.APP, + UserPolicy.IGNORED); - @Action( - path = "/auth/duplicateMethods", - auth = @Auth(methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.API})) - public static class AuthDuplicateMethods {} + private static final AuthSettings AUTH_INTERNAL_WITH_USER = AuthSettings.create( + ImmutableList.of(AuthMethod.INTERNAL, AuthMethod.API), + AuthLevel.USER, + UserPolicy.IGNORED); - @Action( - path = "/auth/internalWithUser", - auth = @Auth(methods = {Auth.AuthMethod.INTERNAL}, minimumLevel = AuthLevel.USER)) - public static class AuthInternalWithUser {} - - @Action( - path = "/auth/wronglyIgnoringUser", - auth = @Auth( - methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API}, - userPolicy = Auth.UserPolicy.IGNORED)) - public static class AuthWronglyIgnoringUser {} + private static final AuthSettings AUTH_WRONGLY_IGNORING_USER = AuthSettings.create( + ImmutableList.of(AuthMethod.INTERNAL, AuthMethod.API), + AuthLevel.APP, + UserPolicy.IGNORED); private final UserService mockUserService = mock(UserService.class); private final HttpServletRequest req = mock(HttpServletRequest.class); @@ -154,14 +132,14 @@ public class RequestAuthenticatorTest { new LegacyAuthenticationMechanism(userService, xsrfTokenManager)); } - private Optional runTest(UserService userService, Class clazz) { + private Optional runTest(UserService userService, AuthSettings auth) { return createRequestAuthenticator(userService) - .authorize(clazz.getAnnotation(Action.class).auth(), req); + .authorize(auth, req); } @Test public void testNoAuthNeeded_noneFound() throws Exception { - Optional authResult = runTest(mockUserService, AuthNone.class); + Optional authResult = runTest(mockUserService, AUTH_NONE); verifyZeroInteractions(mockUserService); assertThat(authResult).isPresent(); @@ -172,7 +150,7 @@ public class RequestAuthenticatorTest { public void testNoAuthNeeded_internalFound() throws Exception { when(req.getHeader("X-AppEngine-QueueName")).thenReturn("__cron"); - Optional authResult = runTest(mockUserService, AuthNone.class); + Optional authResult = runTest(mockUserService, AUTH_NONE); verifyZeroInteractions(mockUserService); assertThat(authResult).isPresent(); @@ -182,7 +160,7 @@ public class RequestAuthenticatorTest { @Test public void testInternalAuth_notInvokedInternally() throws Exception { - Optional authResult = runTest(mockUserService, AuthInternalOnly.class); + Optional authResult = runTest(mockUserService, AUTH_INTERNAL_ONLY); verifyZeroInteractions(mockUserService); assertThat(authResult).isAbsent(); @@ -192,7 +170,7 @@ public class RequestAuthenticatorTest { public void testInternalAuth_success() throws Exception { when(req.getHeader("X-AppEngine-QueueName")).thenReturn("__cron"); - Optional authResult = runTest(mockUserService, AuthInternalOnly.class); + Optional authResult = runTest(mockUserService, AUTH_INTERNAL_ONLY); verifyZeroInteractions(mockUserService); assertThat(authResult).isPresent(); @@ -202,7 +180,7 @@ public class RequestAuthenticatorTest { @Test public void testAnyUserAnyMethod_notLoggedIn() throws Exception { - Optional authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD); assertThat(authResult).isAbsent(); } @@ -211,7 +189,7 @@ public class RequestAuthenticatorTest { public void testAnyUserAnyMethod_xsrfFailure() throws Exception { fakeUserService.setUser(testUser, false); - Optional authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD); assertThat(authResult).isAbsent(); } @@ -222,7 +200,7 @@ public class RequestAuthenticatorTest { when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN)) .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail())); - Optional authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -237,7 +215,7 @@ public class RequestAuthenticatorTest { fakeUserService.setUser(testUser, false); when(req.getMethod()).thenReturn("GET"); - Optional authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -248,7 +226,7 @@ public class RequestAuthenticatorTest { @Test public void testAdminUserAnyMethod_notLoggedIn() throws Exception { - Optional authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD); assertThat(authResult).isAbsent(); } @@ -257,7 +235,7 @@ public class RequestAuthenticatorTest { public void testAdminUserAnyMethod_notAdminUser() throws Exception { fakeUserService.setUser(testUser, false /* isAdmin */); - Optional authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD); assertThat(authResult).isAbsent(); } @@ -266,7 +244,7 @@ public class RequestAuthenticatorTest { public void testAdminUserAnyMethod_xsrfFailure() throws Exception { fakeUserService.setUser(testUser, true); - Optional authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD); assertThat(authResult).isAbsent(); } @@ -277,7 +255,7 @@ public class RequestAuthenticatorTest { when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN)) .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail())); - Optional authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class); + Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -293,7 +271,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setOAuthEnabled(true); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -316,7 +294,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setOAuthEnabled(true); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -337,7 +315,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setUser(testUser); fakeOAuthService.setOAuthEnabled(true); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isAbsent(); } @@ -349,7 +327,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setClientId("wrong-client-id"); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isAbsent(); } @@ -361,7 +339,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setAuthorizedScopes(); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isAbsent(); } @@ -373,7 +351,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setAuthorizedScopes("test-scope1", "test-scope3"); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isAbsent(); } @@ -385,7 +363,7 @@ public class RequestAuthenticatorTest { fakeOAuthService.setAuthorizedScopes("test-scope1", "test-scope2", "test-scope3"); when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN"); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); @@ -405,55 +383,47 @@ public class RequestAuthenticatorTest { public void testAnyUserNoLegacy_failureWithLegacyUser() throws Exception { fakeUserService.setUser(testUser, false /* isAdmin */); - Optional authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class); + Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY); assertThat(authResult).isAbsent(); } @Test - public void testNoMethods_failure() throws Exception { + public void testCheckAuthConfig_NoMethods_failure() throws Exception { thrown.expect(IllegalArgumentException.class, "Must specify at least one auth method"); - runTest(fakeUserService, AuthNoMethods.class); + RequestAuthenticator.checkAuthConfig(AUTH_NO_METHODS); } @Test - public void testMissingInternal_failure() throws Exception { - thrown.expect(IllegalArgumentException.class, - "Auth method INTERNAL must always be specified, and as the first auth method"); - - runTest(fakeUserService, AuthMissingInternal.class); - } - - @Test - public void testWrongMethodOrdering_failure() throws Exception { + public void testCheckAuthConfig_WrongMethodOrdering_failure() throws Exception { thrown.expect(IllegalArgumentException.class, "Auth methods must be unique and strictly in order - INTERNAL, API, LEGACY"); - runTest(fakeUserService, AuthWrongMethodOrdering.class); + RequestAuthenticator.checkAuthConfig(AUTH_WRONG_METHOD_ORDERING); } @Test - public void testDuplicateMethods_failure() throws Exception { + public void testCheckAuthConfig_DuplicateMethods_failure() throws Exception { thrown.expect(IllegalArgumentException.class, "Auth methods must be unique and strictly in order - INTERNAL, API, LEGACY"); - runTest(fakeUserService, AuthDuplicateMethods.class); + RequestAuthenticator.checkAuthConfig(AUTH_DUPLICATE_METHODS); } @Test - public void testInternalWithUser_failure() throws Exception { + public void testCheckAuthConfig_InternalWithUser_failure() throws Exception { thrown.expect(IllegalArgumentException.class, - "Actions with only INTERNAL auth may not require USER auth level"); + "Actions with INTERNAL auth method may not require USER auth level"); - runTest(fakeUserService, AuthInternalWithUser.class); + RequestAuthenticator.checkAuthConfig(AUTH_INTERNAL_WITH_USER); } @Test - public void testWronglyIgnoringUser_failure() throws Exception { + public void testCheckAuthConfig_WronglyIgnoringUser_failure() throws Exception { thrown.expect(IllegalArgumentException.class, "Actions with auth methods beyond INTERNAL must not specify the IGNORED user policy"); - runTest(fakeUserService, AuthWronglyIgnoringUser.class); + RequestAuthenticator.checkAuthConfig(AUTH_WRONGLY_IGNORING_USER); } }