shelf icon indicating copy to clipboard operation
shelf copied to clipboard

How to implement a secure Dart server?

Open warcayac opened this issue 2 years ago • 0 comments

Components

  • Host OS: Debian 10
  • Docker version: 20.10.14, build a224086
  • Docker-compose version: 2.4.1
  • Dart container image source: https://hub.docker.com/_/dart

Structure of my Docker project

.
├── certs
│   ├── cert.pem
│   ├── fullchain.pem
│   └── key.pem
├── dart
│   └── fileserver
│       ├── files
│       └── source
└── docker-compose.yaml
  • source directory contains Dart source files.
  • certs directory contains certificates issued by acme.sh.
  • files directory is a repository for server.
  • source/Dockerfile file is created by Dart when using server-shelf template

docker-compose.yaml

version: "3.8"
services: 
  fileserver:
    build:
      context: ./dart/fileserver/source
    container_name: cyp-fs
    restart: always
    networks: 
      innet:
        ipv4_address: 172.27.0.5
    ports:
      - 8080:8080
      - 443:443
    volumes: 
      - ./dart/fileserver/files:/files
      - ./certs:/certs

networks: 
  # red interna usada por los contenedores únicamente
  innet:
    driver: bridge
    ipam:
     config:
       - subnet: 172.27.0.0/16

dart/fileserver/source/bin/server.dart

import 'dart:io';

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';

import 'package:cyp_files_server/src/exports.dart';

// Configure routes.
final _router = Router()
  ..mount('/private/images/', ImagesApi('files/private/spare_parts/images').router)
  ..mount('/public/text/', StaticAssetsApi('files/public/assets/static_files/text').router)
  ..all('/<name|.*>', fallback());

SecurityContext getSecurityContext() { // Bind with a secure HTTPS connection
  final chain = Platform.script.resolve('certs/fullchain.pem').toFilePath();
  final key = Platform.script.resolve('certs/key.pem').toFilePath();

  return SecurityContext()
    ..useCertificateChain(chain)
    ..usePrivateKey(key, password: 'dartdart');
}

void main(List<String> args) async {
  final useSecureConn = true;
  final context = useSecureConn ? getSecurityContext() : null;
  // Use any available host or container IP (usually `0.0.0.0`).
  final ip = InternetAddress.anyIPv4;

  final _handler = Pipeline()
    .addMiddleware(logRequests())  // logs requests
    .addMiddleware(handleCors())
    .addMiddleware(handleAuth(Env.jwtSecret))
    .addHandler(_router);

  // For running in containers, we respect the PORT environment variable.
  final port = int.parse(Platform.environment['PORT'] ?? (useSecureConn ? '443' : '8080'));
  final server = await serve(_handler, ip, port, securityContext: context);
  print('Serving at http://${server.address.host}:${server.port}');
}

Questions

  • There are three certificates issued (cert, fullchain, key), isn't cert.pem file necessary? If it is, how is it coded?
  • This server run fine on an unsecured protocol, i.e.: http://mydomain.com:8080, but is not working if I try https://mydomain.com, what's wrong?
  • Is password: 'dartdart' necessary for usePrivateKey method?
  • What changes are needed for my server to work on a secure mode by using those certificates?

warcayac avatar Apr 07 '22 06:04 warcayac