ballerina 學習 三十二 編寫安全的程序

ballerina編譯器已經集成了部分安全檢測,在編譯時能夠幫助咱們生成錯誤提示,同時ballerina 標準庫
已經對於常見漏洞高發的地方作了很好的處理,當咱們編寫了有安全隱患的代碼,編譯器就已經提示給
咱們了。
常見的問題sql

  • sql 注入
  • path 操做
  • file 操做
  • 未受權文件訪問
  • 爲校驗的重定向

確保ballerina 標準庫的安全

ballerina 標準庫對於安全敏感的函數以及操做使用@sensitive 註解進行說明,能夠確保容易出現漏洞的數據傳遞
給參數
好比,ballerina 標準庫的select api

public native function select(@sensitive string sqlQuery, typedesc? recordType,
                              boolean loadToMemory = false, Param... parameters)
                             returns @tainted table|error;

安全的使用不可信數據

實際中咱們確定會碰到須要傳遞非可信數據,咱們能夠使用 untaint 表達式進行處理,同時對於返回值咱們能夠使用
@untainted 註解
參考安全

boolean isValid = isNumeric(studentId);
if (isValid) {
   var dt = testDB->select("SELECT NAME FROM STUDENT WHERE ID = " +
                           untaint studentId, ResultStudent);
}

function sanitizeSortColumn (string columnName) returns @untainted string {
   string sanitizedSortColumn = columnName;
   // Sanitize logic to make sure return value is safe
   return sanitizedSortColumn;
}

保護密碼以及secret key

ballerina 提供了api 能夠訪問不一樣源的配置信息,對於配置文件中包含密碼信息的必須加密
處理,框架提供了工具能夠對於配置進行加密框架

ballerina encrypt
按照提示輸入須要加密的名稱,會生成一個加密key,咱們能夠使用配置文件,或者環境變量獲取。
默認會找一個secret.txt的文件,裏面存儲了加密密鑰,請求以後會自動刪除,對於沒有這個文件的
會提示輸入密鑰

認證&&受權

ballerina 的 http 服務能夠配置的方式加強認證以及受權,ballerina 支持jwt 以及basic 模式的認證,
使用basic模式時,用戶信息能夠經過配置文件加載,同時推薦使用https 方式進行數據訪問,加強
安全性ide

  • jwt 認證
    能夠經過http:AuthProvider 進行配置
    參考
import ballerina/http;

http:AuthProvider jwtAuthProvider = {
   scheme:"jwt",
   issuer:"ballerina",
   audience: "ballerina.io",
   clockSkew:10,
   certificateAlias: "ballerina",
   trustStore: {
       path: "${ballerina.home}/bre/security/ballerinaTruststore.p12",
       password: "ballerina"
   }
};

endpoint http:SecureListener secureHelloWorldEp {
   port:9091,
   authProviders:[jwtAuthProvider],
   secureSocket: {
       keyStore: {
           path: "${ballerina.home}/bre/security/ballerinaKeystore.p12",
           password: "ballerina"
       }
   }
};

@http:ServiceConfig {
   basePath:"/hello"
}
service<http:Service> helloWorld bind secureHelloWorldEp {

   @http:ResourceConfig {
       methods:["GET"],
       path:"/"
   }
   sayHello (endpoint caller, http:Request req) {
       http:Response resp = new;
       resp.setTextPayload("Hello, World!");
       _ = caller->respond(resp);
   }
}
  • http basic 認證
    參考代碼
import ballerina/http;

http:AuthProvider basicAuthProvider = {
   scheme:"basic",
   authStoreProvider:"config"
};

endpoint http:SecureListener secureHelloWorldEp {
   port:9091,
   authProviders:[basicAuthProvider],
   secureSocket: {
       keyStore: {
           path: "${ballerina.home}/bre/security/ballerinaKeystore.p12",
           password: "ballerina"
       }
   }
};

@http:ServiceConfig {
   basePath:"/hello",
   authConfig:{
      scopes:["hello"]
   }
}
service<http:Service> helloWorld bind secureHelloWorldEp {

   @http:ResourceConfig {
       methods:["GET"],
       path:"/"
   }
   sayHello (endpoint caller, http:Request req) {
       http:Response resp = new;
       resp.setTextPayload("Hello, World!");
       _ = caller->respond(resp);
   }
}

用戶帳戶配置信息(經過配置文件)函數

sample-users.toml

["b7a.users"]

["b7a.users.generalUser"]
password="@encrypted:{pIQrB9YfCQK1eIWH5d6UaZXA3zr+60JxSBcpa2PY7a8=}"

["b7a.users.admin"]
password="@encrypted:{pIQrB9YfCQK1eIWH5d6UaZXA3zr+60JxSBcpa2PY7a8=}"
scopes="hello"

加載配置工具

ballerina run --config sample-users.toml basic_auth_sample.bal
  • 說明
    在認證服務的同時,咱們能夠配置scope,指定權限範圍,仍是比較方便的

下游服務的認證

實際上就是在client 端加載認證信息,方便調用加密

  • 一個jwt client 的例子
import ballerina/http;

http:AuthProvider jwtAuthProvider = {
   scheme:"jwt",
   propagateToken: true,
   issuer:"ballerina",
   audience: "ballerina.io",
   clockSkew:10,
   certificateAlias: "ballerina",
   trustStore: {
       path: "${ballerina.home}/bre/security/ballerinaTruststore.p12",
       password: "ballerina"
   }
};

endpoint http:SecureListener secureHelloWorldEp {
   port:9091,
   authProviders:[jwtAuthProvider],
   secureSocket: {
       keyStore: {
           path: "${ballerina.home}/bre/security/ballerinaKeystore.p12",
           password: "ballerina"
       }
   }
};

endpoint http:Client downstreamServiceEP {
   url: "https://localhost:9092",
   auth: { scheme: http:JWT_AUTH },
   secureSocket: {
       trustStore: {
           path: "${ballerina.home}/bre/security/ballerinaTruststore.p12",
           password: "ballerina"
       }
   }
};

@http:ServiceConfig {
   basePath:"/hello",
   authConfig:{
      scopes:["hello"]
   }
}
service<http:Service> helloWorld bind secureHelloWorldEp {

   @http:ResourceConfig {
       methods:["GET"],
       path:"/"
   }
   sayHello (endpoint caller, http:Request req) {
       http:Response response = check downstreamServiceEP->get("/update-stats",
                                                         message = untaint req);
       _ = caller->respond(response);
   }
}

// ----------------------------------------------
// Following code creates the downstream service
// ----------------------------------------------

http:AuthProvider downstreamJwtAuthProvider = {
   scheme:"jwt",
   issuer:"ballerina",
   audience: "ballerina.io",
   clockSkew:10,
   certificateAlias: "ballerina",
   trustStore: {
       path: "${ballerina.home}/bre/security/ballerinaTruststore.p12",
       password: "ballerina"
   }
};

endpoint http:SecureListener secureUpdateServiceEp {
   port:9092,
   authProviders:[downstreamJwtAuthProvider],
   secureSocket: {
       keyStore: {
           path: "${ballerina.home}/bre/security/ballerinaKeystore.p12",
           password: "ballerina"
       }
   }
};

@http:ServiceConfig {
   basePath:"/update-stats"
}
service<http:Service> updateService bind secureUpdateServiceEp {

   @http:ResourceConfig {
       methods:["GET"],
       path:"/"
   }
   updateStats (endpoint caller, http:Request req) {
       http:Response resp = new;
       resp.setTextPayload("Downstream Service Received JWT: " +
                           untaint req.getHeader("Authorization"));
       _ = caller->respond(resp);
   }
}

說明

ballerina 的設計以及功能仍是很方便的,功能很齊全。url

參考資料

https://ballerina.io/learn/how-to-write-secure-ballerina-code/設計

相關文章
相關標籤/搜索