Infrastructure

Security and Auth

Security policies control access to encrypted resources.

Ensuring the proper security of data is foundational to the Twisp infrastructure. Out of the box, data is securely encrypted both at rest and in transit and all access is authenticated via JWT tokens issued by the OpenID Connect 1.0 protocol.

Users can configure additional access settings by defining client policies within a CloudFormation template to set permissions on specific operations.

The authentication & authorization flow

The Twisp authentication process uses a policy-based approach to apply specific permissions to a principal granting or denying access to resources.

In a simplified form, the stages for the authentication process are:

  1. A principal issues an HTTPS request with their OIDC JWT and Twisp account IDs in the headers.
  2. The principal name is extracted from the JWT.
  3. Twisp finds the corresponding policies to apply using the principal name.
  4. The resulting policies are evaluated for authorization.

Making an authenticated request

All HTTPS requests to the GraphQL API must provide the following headers to allow for authorization:

Authorization: Bearer <JWT>
x-twisp-account-id: <AWS account id>

The JWT can be issued either with OpenID Connect or AWS IAM.

Authorizing a principal

Within a Twisp::Database::Client configuration, the security principal is the authenticated name of the identity accessing the system. The client authorization system retrieves Policies based on the principal name.

For OIDC, this may be the issuing system URL. For AWS IAM, it may be the IAM role or user name.

// policies.yml
WebClient:
  Type: Twisp::Database::Client
  Properties:
    Principal: !Ref WebClientARN
    Policies:
    - Effect: ALLOW
      Actions:
      - db:Select
      Resources:
      - public.*

Issuing tokens with OpenID Connect (OIDC)

Any JWT generated by an OpenID Connect 1.0 capable issuer is supported by Twisp for authentication. These tokens must be embedded in the Authorization HTTP header.

When an API endpoint receives the JWT, it validates the token signatures against the issuer and—if valid—invokes the endpoint with a security principal set to the issuer iss claim in the token.

All claims from the token are embedded in the context.auth.claims transaction context variable. These claims are available for all security policies.

Issuing tokens with AWS Identity and Access Management (IAM)

Twisp can vend an OpenID Connect token in exchange for any authenticated IAM role or user. This allows a process running under an IAM role to retrieve a Twisp-issued OIDC token for access.

The issuer of these tokens is https://auth.${AWS::Region}.prod.twisp.com/token/iam.

The security principal name that results from these tokens for policy lookup is equal to the original AWS IAM principal name, which is set in the sub field of the token.

Read more about AWS IAM on their official docs.

Defining Policies for a Client

Within the configuration for a Twisp::Database::Client, the Policies property is used to define allow/deny rules for actions and resources.

The Policies property contains a list of Policy mappings. Each Policy defines an Effect (either ALLOW or DENY), a list of Actions and Resources to apply the effect on, and optional Assertions to determine whether or not the policy should be applied.

When the system runs a transaction, it reviews all actions taken against resources to ensure every one is allowed based on the policies defined.

Logical combination of policies

Policies can be defined in any order because they are effectively applied as a chain of logical AND statements scoped to the resource and action in question. When an authenticated principal attempts an action against a particular resource, they must have at least one ALLOW policy applied to the resource/action pair. A single DENY policy on the resource/action pair will block the operation.

Example Schema

The following schema shows a Twisp::Database::Client resource definition with 3 policies applied to a web client principal.

These policies could be interpreted into plain language as:

  1. By default, grant the principal permission to perform CRUD actions on every public resource.
  2. Do not allow the principal to read the ssn property for the customers resource.
  3. Do not allow the principal to delete documents from the customers resource when the address property is not null and the email property does not end with @twisp.com.
// policies.yml
Transform: AWS::Serverless-2016-10-31
Parameters:
  WebClientARN:
    Default: arn:aws:iam::<AWS ACCOUNT ID>:role/site-twisp-com-SiteEdgeRequestRole-1KQFID9FYANM2
    Type: String
Resources:
  WebClient:
    Type: Twisp::Database::Client
    Properties:
      Principal: !Ref WebClientARN
      Policies:
      - Effect: ALLOW
        Actions:
        - db:Insert
        - db:Select
        - db:Update
        - db:Delete
        Resources:
        - public.*
      - Effect: DENY
        Actions:
        - db:Select
        Resources:
        - public.customers.document.ssn
      - Effect: DENY
        Actions:
        - db:Delete
        Resources:
        - public.customers.*
        Assertions:
          HasAddress: |
            has(context.document.address)
          HasTwispEmail: |
            context.document.email.endsWith('@twisp.com')

Controlling access to Actions and Resources

Each Policy allows for the specification of Actions and Resources to allow or deny access to.

In the above example, the second policy is defined such that the principal is denied access to the action db:Select on the public.customers.document.ssn resource.

Twisp defaults to DENY for all actions and resources, so an explicit ALLOW is required for any actions that should be permitted for a given principal.

Values for Resources and Actions on policies support the wildcards * for a greedy match and ? for single character matching.

List of all Actions

The set of values allowed in the Actions list are:

  • db:Select : read a document
  • db:Insert : create a document
  • db:Update : update the value(s) of a document's field(s)
  • db:Delete : delete a document

Format for the Resources ID string

The values for the Resources property of a Policy are resource ID strings. These strings follow the format:

<namespace>.<ledger>.<document|indexes|joins|references>.<propertyName>

Currently the only supported namespace is public, which contains all resources in the Twisp account.

Conditional application of Policies

The Assertions property allows the conditional application of a policy.

Each key in the Assertions contains a Common Expression Language (CEL) expression which is evaluated and combined with other assertions in a logical AND chain. If any condition evaluates to false, then the policy is not applied.

Within the expression, the context object can be used to query properties of documents in the resources requested.

In the example schema above, the Assertions defined on the third policy ensure that the policy will only be applied when both of the following are true:

  • The customer has an address (i.e. the address property is not null)
  • The customer's email ends with @twisp.com

This effectively disables deleting records from the customers resource when they have an address or a Twisp company email.

Encryption

Encryption in transit

Data is encrypted in transit via HTTPS connections for all external and internal API operations.

This protects against man-in-the-middle style attacks and prevents any malicious actors listening in on Twisp web traffic from being able to access the data.

Encryption at rest

All data stored in Twisp is encrypted at rest. Encryption keys are stored in AWS Key Management Service.

This protects against any breaches of the servers where Twisp data is stored. Even if a malicious actor gains access, they will not be able to view the data without the proper decryption keys.

Previous
Computation Engine