import ballerina/http;

// Create an HTTP listener configuration, which will configure a listener to
// accept new connections that are secured via mutual SSL.
// [secureSocket](https://docs.central.ballerina.io/ballerina/http/latest/records/ListenerSecureSocket) record provides the SSL related listener configurations.
http:ListenerConfiguration helloWorldEPConfig = {
    secureSocket: {
        key: {
            certFile: "../resource/path/to/public.crt",
            keyFile: "../resource/path/to/private.key"
        },
        // Enable mutual SSL.
        mutualSsl: {
            verifyClient: http:REQUIRE,
            cert: "../resource/path/to/public.crt"
        },
        // Enable the preferred SSL protocol and its versions.
        protocol: {
            name: http:TLS,
            versions: ["TLSv1.2", "TLSv1.1"]
        },
        // Configure the preferred ciphers.
        ciphers: ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"]
    }
};

// Create a listener endpoint.
listener http:Listener helloWorldEP = new (9095, helloWorldEPConfig);

// Bind the service to the listener endpoint that you declared earlier.
service /helloWorld on helloWorldEP {

    resource function get hello() returns string {
        // Send the response to the caller.
        return "Successful";

    }
}
import ballerina/http;
import ballerina/log;

// Create a client configuration to be passed to the client endpoint.
// Configure the `certFile`, `keyFile` including `cert` which
// is required to enable mutual SSL.
// [secureSocket](https://docs.central.ballerina.io/ballerina/http/latest/records/ClientSecureSocket) record provides the SSL related configurations.
http:ClientConfiguration clientEPConfig = {
    secureSocket: {
        key: {
            certFile: "../resource/path/to/public.crt",
            keyFile: "../resource/path/to/private.key"
        },
        mutualSsl: {
            cert: "../resource/path/to/public.crt"
        },
        protocol: {
            name: http:TLS
        },
        ciphers: ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"]
    }
};

public function main() {
    // Create an HTTP client to interact with the created listener endpoint.
    http:Client clientEP = checkpanic new("https://localhost:9095",
                                          clientEPConfig);
    // Send a GET request to the listener and bind the payload to a string value.
    var payload = clientEP->get("/helloWorld/hello", targetType = string);

    if (payload is string) {
        // Log the retrieved text payload.
        log:printInfo(payload);

    } else {
        // If an error occurs when getting the response or binding payload, log the error.
        log:printError(payload.message());

    }
}

Mutual SSL

Ballerina supports mutual SSL, which is a certificate-based authentication process where two parties (client and server) authenticate each other by verifying the digital certificates. It ensures that both parties are assured of each other’s identity.

For more information on the underlying module, see the HTTP module.

import ballerina/http;
http:ListenerConfiguration helloWorldEPConfig = {
    secureSocket: {
        key: {
            certFile: "../resource/path/to/public.crt",
            keyFile: "../resource/path/to/private.key"
        },

Create an HTTP listener configuration, which will configure a listener to accept new connections that are secured via mutual SSL. secureSocket record provides the SSL related listener configurations.

        mutualSsl: {
            verifyClient: http:REQUIRE,
            cert: "../resource/path/to/public.crt"
        },

Enable mutual SSL.

        protocol: {
            name: http:TLS,
            versions: ["TLSv1.2", "TLSv1.1"]
        },

Enable the preferred SSL protocol and its versions.

        ciphers: ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"]
    }
};

Configure the preferred ciphers.

listener http:Listener helloWorldEP = new (9095, helloWorldEPConfig);

Create a listener endpoint.

service /helloWorld on helloWorldEP {

Bind the service to the listener endpoint that you declared earlier.

    resource function get hello() returns string {
        return "Successful";

Send the response to the caller.

    }
}
# To start the service, navigate to the directory that contains the
# `.bal` file and execute the `bal run` command below.
# (You may need to change the certificate file path, private key file path and
# trusted certificate file path.)
bal run mutual_ssl_service.bal
[ballerina/http] started HTTPS/WSS listener 0.0.0.0:9095
import ballerina/http;
import ballerina/log;
http:ClientConfiguration clientEPConfig = {
    secureSocket: {
        key: {
            certFile: "../resource/path/to/public.crt",
            keyFile: "../resource/path/to/private.key"
        },
        mutualSsl: {
            cert: "../resource/path/to/public.crt"
        },
        protocol: {
            name: http:TLS
        },
        ciphers: ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"]
    }
};

Create a client configuration to be passed to the client endpoint. Configure the certFile, keyFile including cert which is required to enable mutual SSL. secureSocket record provides the SSL related configurations.

public function main() {
    http:Client clientEP = checkpanic new("https://localhost:9095",
                                          clientEPConfig);

Create an HTTP client to interact with the created listener endpoint.

    var payload = clientEP->get("/helloWorld/hello", targetType = string);

Send a GET request to the listener and bind the payload to a string value.

    if (payload is string) {
        log:printInfo(payload);

Log the retrieved text payload.

    } else {
        log:printError(payload.message());

If an error occurs when getting the response or binding payload, log the error.

    }
}
# To start the service, navigate to the directory that contains the
# `.bal` file and execute the `bal run` command along with the Ballerina home path as a config.
# (You may need to change the certificate file path, private key file path and
# trusted certificate file path.)
bal run ssl_client.bal
time = 2021-01-21 21:47:42,768 level = INFO  module = "" message = "Successful"