How am I supposed to store a cert for a deployed app?

Posted September 15, 2021 312 views
DigitalOceanDigitalOcean App Platform

I’m trying to start using digital ocean apps.

My server connects to a digital ocean database, but using ‘ca-certificate.crt’.

I have seen that you shouldn’t put certs in a repo (even though mine is private to just me).

So how should I get the cert onto the app? It’s gotta get it from somewhere right? Why is putting it on the repo less secure?

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Submit an Answer
1 answer

👋 @skeddtemp

Great question, while App Platform doesn’t allow injection of secrets to files yet, there is an easy workaround using environment variables.

I’ve answered this question here: How to include a x509 certificate in Apps

Hope this helps!

  • For some reason it’s still not working for me, even though it appears the file get correctly generated.

    I do a fs.existsSync(‘ca-certificate.crt’) which is true, and my mongo connection string ends with “tlsCAFile=ca-certificate.crt”, and yet I get this error:

    [file-upload-server] [2021-09-15 20:14:03] [server] Error: ENOENT: no such file or directory, open './ca-certificate.crt"'
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Object.openSync (fs.js:462:3)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Object.readFileSync (fs.js:364:35)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at transform (/workspace/node_modules/mongodb/lib/connection_string.js:854:23)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at setOption (/workspace/node_modules/mongodb/lib/connection_string.js:392:36)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Object.parseOptions (/workspace/node_modules/mongodb/lib/connection_string.js:285:9)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at new MongoClient (/workspace/node_modules/mongodb/lib/mongo_client.js:62:46)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Object.<anonymous> (/workspace/queue.js:3:16)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Module._compile (internal/modules/cjs/loader.js:999:30)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    [file-upload-server] [2021-09-15 20:14:03] [server]     at Module.load (internal/modules/cjs/loader.js:863:32) {
    [file-upload-server] [2021-09-15 20:14:03] [server]   errno: -2,
    [file-upload-server] [2021-09-15 20:14:03] [server]   syscall: 'open',
    [file-upload-server] [2021-09-15 20:14:03] [server]   code: 'ENOENT',

    I tried both with and without ./ at the beginning.

    Any idea why?

    • Did you add the part that persists the env var to a file in your run command?

      For example, if your mongo component is called my-mongo-db then you can set the env var like:

      MONGO_DB_CERT=${my-mongo-db.CA_CERT} and then in your run command you can persist this secret to a file like:

      echo "${MONGO_DB_CERT}" > ca-certificate.crt && npm start

      (This assumes your run command is npm start, if it’s not replace that part with your original run command).

      • Yeah my run command is now:

        "echo \"${MONGO_CERT}\" > ca-certificate.crt && concurrently npm:server npm:processor npm:taskrunner --restart-tries -1"

        and this properly prints out the cert data

        if (fs.existsSync('ca-certificate.crt')) console.log('cert file exists:', fs.readFileSync('ca-certificate.crt', {encoding: 'utf-8'}));
        else console.log('cert file was not found');

        it also shows up with the rest of the files expected on the root directory when I do fs.readdirSync('.');

        yet the line after that where it tries to connect to the database is still crashing.

        const client = new MongoClient(process.env.MONGO_URI);

        The uri is the value I got from the database page on DO, same with the cert. The path at the end is just tlsCAFile=ca-certificate.crt

        It’s been working perfectly fine on my home pc.

        • Odd, try changing your run command to:

          echo "${MONGO_CERT}" > ca-certificate.crt && concurrently npm:server npm:processor npm:taskrunner --restart-tries -1

          I used: echo "${CA_CERT}" > ca-certificate.crt && bin/go-info-webserver in the following spec and it worked as expected.

          - cluster_name: my-mongo-db
            engine: MONGODB
            name: my-mongo-db
            production: true
            version: "4"
          name: go-info-webserver
          region: nyc
          - environment_slug: go
            - key: DATABASE_URL
              scope: RUN_TIME
              value: ${my-mongo-db.DATABASE_URL}
            - key: CA_CERT
              scope: RUN_AND_BUILD_TIME
              value: ${my-mongo-db.CA_CERT}
              branch: master
              deploy_on_push: true
              repo: digitalocean/go-info-webserver
            http_port: 8080
            instance_count: 1
            instance_size_slug: basic-xs
            name: go-info-webserver
            - path: /
            run_command: echo "${CA_CERT}" > ca-certificate.crt && bin/go-info-webserver
            source_dir: /
          • I’ve just discovered the problem: I had the connection string value in quotes, which made it end up as double quotes on the config, and the end quote was getting added to the path. After removing them it was able to connect to the database.

            My first DO app is now running successfully, thanks for all your help today!