Connect: Does anyone encrypt the app secrets?

Various source say “data should be encrypted at rest”. Example from Atlassian:

If your app needs to store sensitive data or important configuration data, you should store that within your own infrastructure. Sensitive data should be encrypted at rest. App specific data that is used for security-specific cases should also be contained in your own app’s infrastructure.

I have trouble understanding what it means technologically. The shared secret in Connect apps are certainly highly sensitive:

  • Even if you don’t store customer data yourself at all,
  • Simply having the shared secret for an app that has “READ” permissions allows a hacker to read the contents of Confluence instances from all people who have installed your app: Jira issues, Pages (=trade secrets, confidential information), history, names associated with the history (=PII).
  • Of course the app secret isn’t PII, but it allows access to PII if leaked.

I notice the Spring Boot starter from Atlassian doesn’t encrypt the app secrets by default in the AtlassianHost table. I am not aware that it is a frequent practice in engineering to encrypt a database column.

Does anyone encrypt their app secrets?

1 Like

Yes we encrypt the install payload secrets, it is one of the most sensitive pieces of data we store. The single shared secret means that if that were to leak access to any instance an app is installed in is possible.

3 Likes

@aragot You are correct. This is a limitation of the current Connect Spring Boot and ACE framework implementations.

We are looking at what is required to support this in a way which allows an addon developer to hook in their preferred encryption service. The frameworks, themselves, will not provide the encryption, merely a mechanism to hook encryption into the flow.

I don’t have a timeframe for when this will be available at this moment.

2 Likes

@cmacneill can you pls reference documentation that outlines best practice to hook client secret encryption into the flow? Thanks.

Update: It looks like AWS DynamoDb - where the connect tenant table is stored provides encryption at rest by default.

Hi @UlrichKuhnhardtIzym1

https://developer.atlassian.com/platform/marketplace/security-requirements-more-info/#secure-handling-of-the-sharedsecret expands on how the shared secret should be encrypted. Encryption-at-rest is a good start, but ideally the secret would be encrypted separately (this gives a good audit trail, and makes rotation/re-encryption easier). I’ll see if we can add something to the docs to help.

1 Like

Hey @zsims, is there any new guidance on this? Would you recommend creating a special adapter on the ACE framework that encrypts the key before storage?

1 Like

Hey @GraceKu :wave:, our guidance hasn’t changed here

The security threat here is if an attacker gets access to an app database or server they will have the shared secrets and by extension - potential read access to tenant data

To mitigate this threat, we suggest you:

  • use a platform service such as AWS KMS to generate and store an encryption key, so you can control and audit the access to it.
  • use this key when interacting with the AtlassianHost table to encrypt/decrypt the secret - AWS has documentation with examples on how to use their SDKs to help with this

Though ACE doesn’t have special support for this pattern today, creating your own adapter to solve this consistently across your app is a great idea.

1 Like

Hello

What I’m unsure is how to add the encryption to the existing Atlassian Connect Spring Boot and Atlassian Connect Express libraries. There is no explicit documentation or extension points to add the encryption? My current plan is to do it like this:

So, for Atlassian Connect Spring Boot, I basically ‘overwrite’ the persistence and add a AttributeConverter:

Add a orm-atlassian-host.xml, configure JPA to use this instead of the Atlassian’s orm.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="https://jakarta.ee/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence/orm
          https://jakarta.ee/xml/ns/persistence/orm/orm_3_1.xsd"
                 version="3.1">
    <entity class="com.atlassian.connect.spring.AtlassianHost">
        <entity-listeners>
            <entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener"/>
        </entity-listeners>
        <convert attribute-name="sharedSecret" converter="com.example.EncryptEntityField"/>
        <attributes>
            <id name="clientKey"/>
        </attributes>
    </entity>
</entity-mappings>

For Atlassian Connect Express: Update via @marc : I can register my own storage type which does the encryption.

// Register my own encrypted data store
let stores = require('atlassian-connect-express/lib/store');
stores.register("encrypted-sequelize", function (logger, opts) {
    var original = stores.create("sequelize", logger, opts)
    return {
        get: function (key, clientKey) {
            return original.get(key, clientKey) // do the decryption
        },
        set: function (key, value, clientKey) {
            return original.get(key, value, clientKey) // to the encryption
        },
        // ... Implement & forward the other methods
    };
});

And then use that via configuration in config.json:

  "development": {
    "port": 3000,
    "addonKey": "ch.mibex.confluence.ipython-notebook-dev",
    "errorTemplate": true,
    "store": {
      "adapter": "encrypted-sequelize",
      "dialect": "sqlite",
      "storage": "./development.sqlite",
      "logging": false
    }
  },
  ...

Better ways on how to add it would be appreciated.

1 Like

You could write your own database driver, which does the encryption.