Skip to content

Security Considerations

Bob Vawter edited this page Jun 13, 2024 · 8 revisions

Security Considerations

Changefeeds

At a high level, Replicator accepts network connections to apply arbitrary mutations to the target cluster. In order to limit the scope of access, JSON Web Tokens are used to authorize incoming connections and limit them to writing to a subset of the SQL databases or user-defined schemas in the target cluster.

A minimally-acceptable JWT claim is shown below. It includes the standard jti token identifier field, and a custom claim for Replicator. This custom claim is defined in a globally-unique namespace and most JWT-enabled authorization providers support adding custom claims. It contains a list of one or more target databases or user-defined schemas. Wildcards for databases or schema names are supported.

Acceptable JWT tokens must be signed with RSA or EC keys. HMAC and None signatures are rejected. The PEM-formatted public signing keys must be added to the _replicator.jwt_public_keys table. If a specific token needs to be revoked, its jti value can be added to the _replicator.jwt_revoked_ids table. These tables will be re-read every minute by the Replicator process. A HUP signal can be sent to force an early refresh.

The encoded token is provided to the CREATE CHANGEFEED using the WITH webhook_auth_header='Bearer <encoded token>' option. In order to support older versions of CockroachDB, the encoded token may also be specified as a query parameter ?access_token=<encoded token>. Note that query parameters may be logged by intermediate loadbalancers, so caution should be taken.

Token Quickstart

This example uses OpenSSL, but the ultimate source of the key materials doesn't matter, as long as you have PEM-encoded RSA or EC keys.

# Generate a EC private key using OpenSSL.
openssl ecparam -out ec.key -genkey -name prime256v1

# Write the public key components to a separate file.
openssl ec -in ec.key -pubout -out ec.pub

# Upload the public key for all instances of Replicator to find it.
cockroach sql -e "INSERT INTO _replicator.jwt_public_keys (public_key) VALUES ('$(cat ec.pub)')"

# Reload configuration, or wait one minute.
killall -HUP replicator

# Generate a token which can write to the ycsb.public schema.
# The key can be decoded using the debugger at https://jwt.io.
# Add the contents of out.jwt to the CREATE CHANGEFEED command:
# WITH webhook_auth_header='Bearer <out.jwt>'
replicator make-jwt -k ec.key -a ycsb.public -o out.jwt

External JWT Providers

The make-jwt subcommand also supports a --claim option, which will simply print a JWT claim that can be signed by your existing JWT provider. The PEM-formatted public key or keys for that provider will need to be inserted into tho _replicator.jwt_public_keys table, as above. The iss (issuers) and jti (token id) fields will likely be specific to your auth provider, but the custom claim must be retained in its entirety.

Usage:
  replicator make-jwt -key pk.pem -a database.schema -a other_database.schema ... [flags]

Examples:
# Generate a EC private key using OpenSSL.
openssl ecparam -out ec.key -genkey -name prime256v1

# Write the public key components to a separate file.
openssl ec -in ec.key -pubout -out ec.pub

# Generate a token which can write to the ycsb.public schema.
# The key can be decoded using the debugger at https://jwt.io
replicator make-jwt -k ec.key -a ycsb.public -o out.jwt

# Upload the public key for Replicator to find it.
cockroach sql -e "INSERT INTO _replicator.jwt_public_keys (public_key) VALUES ('$(cat ec.pub)')"

# Reload configuration, or wait a minute.
killall -HUP replicator

Flags:
  -a, --allow strings   one or more 'database.schema' identifiers
      --claim           if true, print a minimal JWT claim, instead of signing
  -k, --key string      the path to a PEM-encoded private key to sign the token with
  -o, --out string      a file to write the token to

Global Flags:
      --gracePeriod duration    allow background processes to exit (default 30s)
      --logDestination string   write logs to a file, instead of stdout
      --logFormat string        choose log output format [ fluent, text ] (default "text")
  -v, --verbose count           increase logging verbosity to debug; repeat for trace
# The -a flag may be repeated to create a claim for multiple schemas.
replicator make-jwt -a 'database.schema' --claim`
{
  "iss": "replicator",
  "jti": "d5ffa211-8d54-424b-819a-bc19af9202a5",
  "https://github.com/cockroachdb/replicator": {
    "schemas": [
      [
        "database",
        "schema"
      ]
    ]
  }
}

Supply chain

The replicator version subcommand will print all Golang modules that are part of the build. The output includes the module name, go.mod checksum, and version. This can be used to determine if any particular build may be subject to a vulnerability from an upstream package. Dependabot is used to automatically upgrade go modules.

Binaries that are uploaded to the distribution bucket or to DockerHub are built by a GitHub Actions workflow, running on GitHub-managed builders.

Clone this wiki locally