// Unwraps a rpcError and returns the correct error type. func unwrapError(rpcError *rpcError) error { if rpcError != nil { switch rpcError.Type { case "InternalServerError": return core.InternalServerError(rpcError.Value) case "NotSupportedError": return core.NotSupportedError(rpcError.Value) case "MalformedRequestError": return core.MalformedRequestError(rpcError.Value) case "UnauthorizedError": return core.UnauthorizedError(rpcError.Value) case "NotFoundError": return core.NotFoundError(rpcError.Value) case "SignatureValidationError": return core.SignatureValidationError(rpcError.Value) case "NoSuchRegistrationError": return core.NoSuchRegistrationError(rpcError.Value) case "TooManyRPCRequestsError": return core.TooManyRPCRequestsError(rpcError.Value) case "RateLimitedError": return core.RateLimitedError(rpcError.Value) default: if strings.HasPrefix(rpcError.Type, "urn:") { return &probs.ProblemDetails{ Type: probs.ProblemType(rpcError.Type), Detail: rpcError.Value, HTTPStatus: rpcError.HTTPStatus, } } return errors.New(rpcError.Value) } } return nil }
// Unwraps a rpcError and returns the correct error type. func unwrapError(rpcError *rpcError) error { if rpcError != nil { switch rpcError.Type { case "InternalServerError": return core.InternalServerError(rpcError.Value) case "NotSupportedError": return core.NotSupportedError(rpcError.Value) case "MalformedRequestError": return core.MalformedRequestError(rpcError.Value) case "UnauthorizedError": return core.UnauthorizedError(rpcError.Value) case "NotFoundError": return core.NotFoundError(rpcError.Value) case "SyntaxError": return core.SyntaxError(rpcError.Value) case "SignatureValidationError": return core.SignatureValidationError(rpcError.Value) case "CertificateIssuanceError": return core.CertificateIssuanceError(rpcError.Value) case "NoSuchRegistrationError": return core.NoSuchRegistrationError(rpcError.Value) case "TooManyRPCRequestsError": return core.TooManyRPCRequestsError(rpcError.Value) case "RateLimitedError": return core.RateLimitedError(rpcError.Value) case "ServiceUnavailableError": return core.ServiceUnavailableError(rpcError.Value) default: return errors.New(rpcError.Value) } } return nil }
func (ra *RegistrationAuthorityImpl) checkLimits(ctx context.Context, names []string, regID int64) error { limits := ra.rlPolicies if limits.TotalCertificates.Enabled() { totalIssued, err := ra.getIssuanceCount(ctx) if err != nil { return err } if totalIssued >= ra.rlPolicies.TotalCertificates.Threshold { domains := strings.Join(names, ",") ra.totalCertsStats.Inc("Exceeded", 1) ra.log.Info(fmt.Sprintf("Rate limit exceeded, TotalCertificates, regID: %d, domains: %s, totalIssued: %d", regID, domains, totalIssued)) return core.RateLimitedError("Certificate issuance limit reached") } ra.totalCertsStats.Inc("Pass", 1) } if limits.CertificatesPerName.Enabled() { err := ra.checkCertificatesPerNameLimit(ctx, names, limits.CertificatesPerName, regID) if err != nil { return err } } if limits.CertificatesPerFQDNSet.Enabled() { err := ra.checkCertificatesPerFQDNSetLimit(ctx, names, limits.CertificatesPerFQDNSet, regID) if err != nil { return err } } return nil }
func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(names []string, limit cmd.RateLimitPolicy, regID int64) error { names, err := domainsForRateLimiting(names) if err != nil { return err } now := ra.clk.Now() windowBegin := limit.WindowBegin(now) counts, err := ra.SA.CountCertificatesByNames(names, windowBegin, now) if err != nil { return err } var badNames []string for _, name := range names { count, ok := counts[name] if !ok { // Shouldn't happen, but let's be careful anyhow. return errors.New("StorageAuthority failed to return a count for every name") } if count >= limit.GetThreshold(name, regID) { badNames = append(badNames, name) } } if len(badNames) > 0 { return core.RateLimitedError(fmt.Sprintf( "Too many certificates already issued for: %s", strings.Join(badNames, ", "))) } return nil }
// Unwraps a rpcError and returns the correct error type. func unwrapError(rpcError rpcError) (err error) { if rpcError.Value != "" { switch rpcError.Type { case "InternalServerError": err = core.InternalServerError(rpcError.Value) case "NotSupportedError": err = core.NotSupportedError(rpcError.Value) case "MalformedRequestError": err = core.MalformedRequestError(rpcError.Value) case "UnauthorizedError": err = core.UnauthorizedError(rpcError.Value) case "NotFoundError": err = core.NotFoundError(rpcError.Value) case "SyntaxError": err = core.SyntaxError(rpcError.Value) case "SignatureValidationError": err = core.SignatureValidationError(rpcError.Value) case "CertificateIssuanceError": err = core.CertificateIssuanceError(rpcError.Value) case "NoSuchRegistrationError": err = core.NoSuchRegistrationError(rpcError.Value) case "TooManyRPCRequestsError": err = core.TooManyRPCRequestsError(rpcError.Value) case "RateLimitedError": err = core.RateLimitedError(rpcError.Value) default: err = errors.New(rpcError.Value) } } return }
func unwrapError(err error) error { code := grpc.Code(err) errBody := grpc.ErrorDesc(err) switch code { case InternalServerError: return core.InternalServerError(errBody) case NotSupportedError: return core.NotSupportedError(errBody) case MalformedRequestError: return core.MalformedRequestError(errBody) case UnauthorizedError: return core.UnauthorizedError(errBody) case NotFoundError: return core.NotFoundError(errBody) case SignatureValidationError: return core.SignatureValidationError(errBody) case NoSuchRegistrationError: return core.NoSuchRegistrationError(errBody) case RateLimitedError: return core.RateLimitedError(errBody) case LengthRequiredError: return core.LengthRequiredError(errBody) case BadNonceError: return core.BadNonceError(errBody) default: return err } }
func TestWrapError(t *testing.T) { testCases := []error{ core.InternalServerError("foo"), core.NotSupportedError("foo"), core.MalformedRequestError("foo"), core.UnauthorizedError("foo"), core.NotFoundError("foo"), core.SignatureValidationError("foo"), core.CertificateIssuanceError("foo"), core.NoSuchRegistrationError("foo"), core.RateLimitedError("foo"), core.TooManyRPCRequestsError("foo"), errors.New("foo"), } for _, c := range testCases { wrapped := wrapError(c) test.AssertEquals(t, wrapped.Type, reflect.TypeOf(c).Name()) test.AssertEquals(t, wrapped.Value, "foo") unwrapped := unwrapError(wrapped) test.AssertEquals(t, wrapped.Type, reflect.TypeOf(unwrapped).Name()) test.AssertEquals(t, unwrapped.Error(), "foo") } complicated := []struct { given error expected error }{ { &probs.ProblemDetails{ Type: probs.ConnectionProblem, Detail: "whoops", HTTPStatus: 417, }, &probs.ProblemDetails{ Type: probs.ConnectionProblem, Detail: "whoops", HTTPStatus: 417, }, }, { &probs.ProblemDetails{Type: "invalid", Detail: "hm"}, errors.New("hm"), }, { errors.New(""), errors.New(""), }, } for i, tc := range complicated { actual := unwrapError(wrapError(tc.given)) if !reflect.DeepEqual(tc.expected, actual) { t.Errorf("rpc error wrapping case %d: want %#v, got %#v", i, tc.expected, actual) } } }
func (ra *RegistrationAuthorityImpl) checkCertificatesPerFQDNSetLimit(ctx context.Context, names []string, limit cmd.RateLimitPolicy, regID int64) error { count, err := ra.SA.CountFQDNSets(ctx, limit.Window.Duration, names) if err != nil { return err } names = core.UniqueLowerNames(names) if int(count) > limit.GetThreshold(strings.Join(names, ","), regID) { return core.RateLimitedError(fmt.Sprintf( "Too many certificates already issued for exact set of domains: %s", strings.Join(names, ","), )) } return nil }
func (ra *RegistrationAuthorityImpl) checkRegistrationLimit(ip net.IP) error { limit := ra.rlPolicies.RegistrationsPerIP if limit.Enabled() { now := ra.clk.Now() count, err := ra.SA.CountRegistrationsByIP(ip, limit.WindowBegin(now), now) if err != nil { return err } if count >= limit.GetThreshold(ip.String(), noRegistrationID) { return core.RateLimitedError("Too many registrations from this IP") } } return nil }
func checkPendingAuthorizationLimit(sa core.StorageGetter, limit *cmd.RateLimitPolicy, regID int64) error { if limit.Enabled() { count, err := sa.CountPendingAuthorizations(regID) if err != nil { return err } // Most rate limits have a key for overrides, but there is no meaningful key // here. noKey := "" if count > limit.GetThreshold(noKey, regID) { return core.RateLimitedError("Too many currently pending authorizations.") } } return nil }
func (ra *RegistrationAuthorityImpl) checkRegistrationLimit(ip net.IP) error { limit := ra.rlPolicies.RegistrationsPerIP if limit.Enabled() { now := ra.clk.Now() count, err := ra.SA.CountRegistrationsByIP(ip, limit.WindowBegin(now), now) if err != nil { return err } if count >= limit.GetThreshold(ip.String(), noRegistrationID) { ra.regByIPStats.Inc("Exceeded", 1) ra.log.Info(fmt.Sprintf("Rate limit exceeded, RegistrationsByIP, IP: %s", ip)) return core.RateLimitedError("Too many registrations from this IP") } ra.regByIPStats.Inc("Pass", 1) } return nil }
func (ra *RegistrationAuthorityImpl) checkCertificatesPerNameLimit(ctx context.Context, names []string, limit cmd.RateLimitPolicy, regID int64) error { names, err := domainsForRateLimiting(names) if err != nil { return err } now := ra.clk.Now() windowBegin := limit.WindowBegin(now) counts, err := ra.SA.CountCertificatesByNames(ctx, names, windowBegin, now) if err != nil { return err } var badNames []string for _, name := range names { count, ok := counts[name] if !ok { // Shouldn't happen, but let's be careful anyhow. return errors.New("StorageAuthority failed to return a count for every name") } if count >= limit.GetThreshold(name, regID) { badNames = append(badNames, name) } } if len(badNames) > 0 { // check if there is already a existing certificate for // the exact name set we are issuing for. If so bypass the // the certificatesPerName limit. exists, err := ra.SA.FQDNSetExists(ctx, names) if err != nil { return err } if exists { ra.certsForDomainStats.Inc("FQDNSetBypass", 1) return nil } domains := strings.Join(badNames, ", ") ra.certsForDomainStats.Inc("Exceeded", 1) ra.log.Info(fmt.Sprintf("Rate limit exceeded, CertificatesForDomain, regID: %d, domains: %s", regID, domains)) return core.RateLimitedError(fmt.Sprintf( "Too many certificates already issued for: %s", domains)) } ra.certsForDomainStats.Inc("Pass", 1) return nil }
func (ra *RegistrationAuthorityImpl) checkTotalCertificatesLimit() error { totalCertLimits := ra.rlPolicies.TotalCertificates() ra.tiMu.RLock() defer ra.tiMu.RUnlock() // If last update of the total issued count was more than five minutes ago, // or not yet updated, fail. if ra.clk.Now().After(ra.totalIssuedLastUpdate.Add(5*time.Minute)) || ra.totalIssuedLastUpdate.IsZero() { return core.InternalServerError(fmt.Sprintf("Total certificate count out of date: updated %s", ra.totalIssuedLastUpdate)) } if ra.totalIssuedCount >= totalCertLimits.Threshold { ra.totalCertsStats.Inc("Exceeded", 1) ra.log.Info(fmt.Sprintf("Rate limit exceeded, TotalCertificates, totalIssued: %d, lastUpdated %s", ra.totalIssuedCount, ra.totalIssuedLastUpdate)) return core.RateLimitedError("Global certificate issuance limit reached. Try again in an hour.") } ra.totalCertsStats.Inc("Pass", 1) return nil }
func (ra *RegistrationAuthorityImpl) checkLimits(names []string, regID int64) error { limits := ra.rlPolicies if limits.TotalCertificates.Enabled() { totalIssued, err := ra.getIssuanceCount() if err != nil { return err } if totalIssued >= ra.rlPolicies.TotalCertificates.Threshold { return core.RateLimitedError("Certificate issuance limit reached") } } if limits.CertificatesPerName.Enabled() { err := ra.checkCertificatesPerNameLimit(names, limits.CertificatesPerName, regID) if err != nil { return err } } return nil }
func (ra *RegistrationAuthorityImpl) checkPendingAuthorizationLimit(regID int64) error { limit := ra.rlPolicies.PendingAuthorizationsPerAccount if limit.Enabled() { count, err := ra.SA.CountPendingAuthorizations(regID) if err != nil { return err } // Most rate limits have a key for overrides, but there is no meaningful key // here. noKey := "" if count >= limit.GetThreshold(noKey, regID) { ra.pendAuthByRegIDStats.Inc("Exceeded", 1) ra.log.Info(fmt.Sprintf("Rate limit exceeded, PendingAuthorizationsByRegID, regID: %d", regID)) return core.RateLimitedError("Too many currently pending authorizations.") } ra.pendAuthByRegIDStats.Inc("Pass", 1) } return nil }
func TestErrors(t *testing.T) { testcases := []struct { err error expectedCode codes.Code }{ {core.MalformedRequestError("test 1"), MalformedRequestError}, {core.NotSupportedError("test 2"), NotSupportedError}, {core.UnauthorizedError("test 3"), UnauthorizedError}, {core.NotFoundError("test 4"), NotFoundError}, {core.LengthRequiredError("test 5"), LengthRequiredError}, {core.SignatureValidationError("test 6"), SignatureValidationError}, {core.RateLimitedError("test 7"), RateLimitedError}, {core.BadNonceError("test 8"), BadNonceError}, {core.NoSuchRegistrationError("test 9"), NoSuchRegistrationError}, {core.InternalServerError("test 10"), InternalServerError}, } for _, tc := range testcases { wrappedErr := wrapError(tc.err) test.AssertEquals(t, grpc.Code(wrappedErr), tc.expectedCode) test.AssertEquals(t, tc.err, unwrapError(wrappedErr)) } }
func TestWrapError(t *testing.T) { testCases := []error{ core.InternalServerError("foo"), core.NotSupportedError("foo"), core.MalformedRequestError("foo"), core.UnauthorizedError("foo"), core.NotFoundError("foo"), core.SyntaxError("foo"), core.SignatureValidationError("foo"), core.CertificateIssuanceError("foo"), core.NoSuchRegistrationError("foo"), core.RateLimitedError("foo"), core.TooManyRPCRequestsError("foo"), } for _, c := range testCases { wrapped := wrapError(c) test.AssertEquals(t, wrapped.Type, reflect.TypeOf(c).Name()) test.AssertEquals(t, wrapped.Value, "foo") unwrapped := unwrapError(wrapped) test.AssertEquals(t, wrapped.Type, reflect.TypeOf(unwrapped).Name()) test.AssertEquals(t, unwrapped.Error(), "foo") } }