Skip to content

Commit

Permalink
feat: apitoken types to support prefixes (#65684)
Browse files Browse the repository at this point in the history
In support of getsentry/rfcs#32. 

Add a nullable `token_type` column to the `ApiToken` model. This will be
used to help us identify the different kinds of API tokens we have in
the application via a prefix. With this, we'll be able to integrate with
GitHub and others' secret scanning program to prevent token leaks.
Legacy (e.g. tokens that already exist) will have a null value here, so
we'll know they are not one of our new tokens with the prefix format
once all tokens are stored solely as hashed values.
  • Loading branch information
mdtro authored Feb 23, 2024
1 parent bad358c commit 14814e5
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 308 deletions.
2 changes: 1 addition & 1 deletion migrations_lockfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ feedback: 0004_index_together
hybridcloud: 0011_add_hybridcloudapitoken_index
nodestore: 0002_nodestore_no_dictfield
replays: 0004_index_together
sentry: 0652_alert_rule_activation_condition
sentry: 0653_apitoken_add_token_type
social_auth: 0002_default_auto_field
31 changes: 31 additions & 0 deletions src/sentry/migrations/0653_apitoken_add_token_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 5.0.2 on 2024-02-23 04:05

from django.db import migrations, models

from sentry.new_migrations.migrations import CheckedMigration


class Migration(CheckedMigration):
# This flag is used to mark that a migration shouldn't be automatically run in production. For
# the most part, this should only be used for operations where it's safe to run the migration
# after your code has deployed. So this should not be used for most operations that alter the
# schema of a table.
# Here are some things that make sense to mark as dangerous:
# - Large data migrations. Typically we want these to be run manually by ops so that they can
# be monitored and not block the deploy for a long period of time while they run.
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
# have ops run this and not block the deploy. Note that while adding an index is a schema
# change, it's completely safe to run the operation after the code has deployed.
is_dangerous = False

dependencies = [
("sentry", "0652_alert_rule_activation_condition"),
]

operations = [
migrations.AddField(
model_name="apitoken",
name="token_type",
field=models.CharField(max_length=7, null=True),
),
]
2 changes: 2 additions & 0 deletions src/sentry/models/apitoken.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from sentry.models.apiscopes import HasApiScopes
from sentry.models.outbox import OutboxCategory
from sentry.types.region import find_all_region_names
from sentry.types.token import AuthTokenType

DEFAULT_EXPIRATION = timedelta(days=30)

Expand All @@ -42,6 +43,7 @@ class ApiToken(ReplicatedControlModel, HasApiScopes):
name = models.CharField(max_length=255, null=True)
token = models.CharField(max_length=64, unique=True, default=generate_token)
hashed_token = models.CharField(max_length=128, null=True)
token_type = models.CharField(max_length=7, choices=AuthTokenType, null=True)
token_last_characters = models.CharField(max_length=4, null=True)
refresh_token = models.CharField(max_length=64, unique=True, null=True, default=generate_token)
hashed_refresh_token = models.CharField(max_length=128, null=True)
Expand Down
16 changes: 16 additions & 0 deletions src/sentry/types/token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.db import models


class AuthTokenType(models.TextChoices):
"""
Represents the various API/auth token types in the Sentry code base.
The values equate to the expected prefix of each of the token types.
"""

USER = "sntryu_"
ORG = "sntrys_"
USER_APP = "sntrya_"
INTEGRATION = "sntryi_"

# tokens created prior to our prefixing
__empty__ = None
Loading

0 comments on commit 14814e5

Please sign in to comment.