Skip to content
This repository was archived by the owner on Jul 12, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/apiserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func realMain(ctx context.Context) error {
chaffDet := chaff.HeaderDetector("X-Chaff")

// POST /api/verify
verifyChaff, err := chaff.NewTracker(chaff.NewJSONResponder(encodeVerifyReponse), chaff.DefaultCapacity)
verifyChaff, err := chaff.NewTracker(chaff.NewJSONResponder(encodeVerifyResponse), chaff.DefaultCapacity)
if err != nil {
return fmt.Errorf("error creating chaffer: %v", err)
}
Expand Down Expand Up @@ -212,7 +212,7 @@ func makePadFromChaff(s string) api.Padding {
return api.Padding(s)
}

func encodeVerifyReponse(s string) interface{} {
func encodeVerifyResponse(s string) interface{} {
return api.VerifyCodeResponse{Padding: makePadFromChaff(s)}
}

Expand Down
4 changes: 3 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Possible error code responses. New error codes may be added in future releases.
| `code_not_found` | 400 | No | The server has no record of that code. |
| `invalid_test_type` | 400 | No | The client sent an accept of an unrecgonized test type |
| `missing_date` | 400 | No | The realm requires either a test or symptom date, but none was provided. |
| `uuid_already_exists` | 409 | No | The UUID has already been used for an issued code |
| `maintenance_mode ` | 429 | Yes | The server is temporarily down for maintenance. Wait and retry later. |
| `unsupported_test_type` | 412 | No | The code may be valid, but represents a test type the client cannot process. User may need to upgrade software. |
| | 500 | Yes | Internal processing error, may be successful on retry. |

Expand Down Expand Up @@ -152,7 +154,7 @@ Possible error code responses. New error codes may be added in future releases.
| `token_invalid` | 400 | No | The provided token is invalid, or already used to generate a certificate |
| `token_expired` | 400 | No | Code invalid or used, user may need to obtain a new code. |
| `hmac_invalid` | 400 | No | The `ekeyhmac` field, when base64 decoded is not the right size (32 bytes) |
| `uuid_already_exists` | 409 | No | The UUID has already been used for an issued code |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to delete this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's in the wrong section, I moved it up. That's a response for Issue

| `maintenance_mode ` | 429 | Yes | The server is temporarily down for maintenance. Wait and retry later. |
| | 500 | Yes | Internal processing error, may be successful on retry. |

# Admin APIs
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ const (
ErrHMACInvalid = "hmac_invalid"
// ErrUUIDAlreadyExists indicates that the UUID has already been used for an issued code.
ErrUUIDAlreadyExists = "uuid_already_exists"
// ErrMaintenanceMode indicates that the server is read-only for maintenance.
ErrMaintenanceMode = "maintenance_mode"
)

// ErrorReturn defines the common error type.
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/admin_server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type AdminAPIServerConfig struct {
// production environments.
DevMode bool `env:"DEV_MODE"`

// If MaintenanceMode is true, the server is temporarily read-only and will not issue codes.
MaintenanceMode bool `env:"MAINTENANCE_MODE"`

// Rate limiting configuration
RateLimit ratelimit.Config

Expand Down Expand Up @@ -109,3 +112,7 @@ func (c *AdminAPIServerConfig) GetRateLimitConfig() *ratelimit.Config {
func (c *AdminAPIServerConfig) ObservabilityExporterConfig() *observability.Config {
return &c.Observability
}

func (c *AdminAPIServerConfig) IsMaintenanceMode() bool {
return c.MaintenanceMode
}
1 change: 1 addition & 0 deletions pkg/config/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ type IssueAPIConfig interface {
GetEnforceRealmQuotas() bool
GetRateLimitConfig() *ratelimit.Config
GetENXRedirectDomain() string
IsMaintenanceMode() bool
}
7 changes: 7 additions & 0 deletions pkg/config/server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ type ServerConfig struct {
// This includes CSRF protection base cookie. You want this false in production (the default).
DevMode bool `env:"DEV_MODE"`

// If MaintenanceMode is true, the server is temporarily read-only and will not issue codes.
MaintenanceMode bool `env:"MAINTENANCE_MODE"`

// Rate limiting configuration
RateLimit ratelimit.Config
}
Expand Down Expand Up @@ -154,6 +157,10 @@ func (c *ServerConfig) ObservabilityExporterConfig() *observability.Config {
return &c.Observability
}

func (c *ServerConfig) IsMaintenanceMode() bool {
return c.MaintenanceMode
}

// FirebaseConfig represents configuration specific to firebase auth.
type FirebaseConfig struct {
APIKey string `env:"FIREBASE_API_KEY,required"`
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/issueapi/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ func validateDate(date, minDate, maxDate time.Time, tzOffset int) (*time.Time, e

func (c *Controller) HandleIssue() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if c.config.IsMaintenanceMode() {
c.h.RenderJSON(w, http.StatusTooManyRequests,
api.Errorf("server is read-only for maintenance").WithCode(api.ErrMaintenanceMode))
return
}

ctx := observability.WithBuildInfo(r.Context())

logger := logging.FromContext(ctx).Named("issueapi.HandleIssue")
Expand Down