golang-apex-api-security

command module
v0.0.0-...-ca3b33c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2020 License: MIT Imports: 6 Imported by: 0

README

Golang HTTP Signature Signer for APEX

Codeship Status for robincher/golang-apex-api-security Go Report Card Open Source Love PRs Welcome GuardRails badge

A golang http signature library for APEX. It main purpose is to provide a quick utility that generates HTTP security headers for authenticating with secured APEX endpoints

This library is still in BETA Testing stage

Security Standards

  1. APEX L1 - HMAC256 HTTP Signature
  2. APEX L2 - RSA256 HTTP Signature

Currently still in designing and testing phase

Table of Contents

Getting Started

Installation
go get -u github.com/GovTechSG/golang-apex-api-security

If you have errors about package not found , please verify your GOPATH and ensure your project is residing at the right directory. For more information about setting GOPATH, go here

Walkthrough
Defining the Request Parameters as a struct
// APIParam -  Defining the request struct
type APIParam struct {
	Realm        string `json:"realm"`
	AppID        string `json:"appId"`
	AuthPrefix   string `json:"authPrefix"`
	Secret       string `json:"secret"`
	InvokeURL    string `json:"invokeUrl"`
	SignatureURL string `json:"signatureUrl"`

	HTTPMethod string `json:"httpMethod"`
	Signature  string `json:"signature"`

	PrivateCertFileName string `json:"privateCertFileName"`
	Passphrase          string
	SignatureMethod     string `json:"signatureMethod"`
	Nonce               string `json:"nonce"`
	Timestamp           string `json:"timestamp"`
	Version             string `json:"version"`

	QueryString map[string]interface{} `json:"queryString"`
	FormData    map[string]interface{} `json:"formData"`
}
Invoking the helper utility

Please appened the values based on your own settings and requirements.

requestOpts := APIParam{
		Realm:    "https://portal.example.com,
		AppID: "AppID123",
		AuthPrefix: "apex_lg_l1",
        Secret: "Secret",
        InvokeURL: "https://something.api.gov.sg/v1/resource",
        SignatureURL: ""https://something.api.i.gov.sg/v1/resource""
}

apexAuthHeader, err := getSignatureToken(requestOpts)
Appending to the HTTP header
import net/http example

var req *http.Request
req.Header.Add("Authorization", apexAuthHeader)
Running unit test with coverage

The test data will be pulled from a central package that is shared across all APEX security librares.

You can refer them here

Run the following shell script to pull the test data , execute unit test and print out the test coverage.

./scripts/test_coverage.sh
Request Parameters

This section describes each of the parameters and it purpose.

Mandatory Parameters
  1. AppID

Apex App ID. The App needs to be approved and activated by the API provider. This value can be obtained from the gateway portal.

  1. AuthPrefix

API gateway-specific authorization scheme for a specific gateway zone. Takes 1 of 4 possible values.

var authPrefix = 'Apex_l1_ig';
// or
var authPrefix = 'Apex_l1_eg';
// or
var authPrefix = 'Apex_l2_ig';
// or
var authPrefix = 'Apex_l2_eg';
  1. HTTPMethod

The standard HTTP method required for the target resource

  1. InvokeURL The full API endpoint path that you will be invoking , for example https://my-apex-api.api.gov.sg/api/my/specific/data

IMPORTANT NOTE
Must be the endpoint URL as served from the Apex gateway, from the domain api.gov.sg. This may differ from the actual HTTP endpoint that you are calling, for example if it were behind a proxy with a different URL.**

  1. SignatureURL

The API endpoint that is only internally recognised. For examples : a) https://my-apex-api.i.api.gov.sg/api/my/specific/data b) https://my-apex-api.e.api.gov.sg/api/my/specific/data

We have plans to remove this inconsistency in the near future, so for now do indicate this parameter into the request parameters, else the signature verification will failed.

5a. Secret - For APEX L1 Security

If the API you are accessing is secured with an APEX L1 policy, you need to provide the generated App secret that corresponds to the AppID provided.

5b. PrivateCertFileName andPassphrase` - For APEX L2 Security

If the API you are access is secured with an APEX L2 policy, you need to provide the private key and passphrase corresponding to the public key uploaded for AppID.

var keyPath = "/path/to/my/private.key"
var passphrase = "somepassword"
Optional Parameters
  1. Realm

An identifier for the caller, this can be set to any value. (eg https://portal.example.com)

  1. QueryString / FormData

IMPORTANT NOTE If you pass in the params in QueryString or FormData, please remove the query parameters from both SignatureURL and InvokeURL parameter

2b. QueryString

Object representation of URL query parameters, for the API.

For example, the API endpoint is https://example.com/v1/api?key=value , then you have you pass in the params in this manner below :

var queryString [][]string
queryString = append(queryString, []string{"key", "value"})

2b. FormData

Object representation of form data (x-www-form-urlencoded) passed during HTTP POST / HTTP PUT requests

var formData [][]string
formData = append(formData, []string{"key", "value"})

  1. Nonce An arbitrary string, needs to be different after each successful API call. Defaults to 32 bytes random value encoded in base64.

  2. Timestamp A unix timestamp. Defaults to the current unix timestamp.

Example

Run the example app to see how an authorization token for Apex is constructed

go run example.go

Contributing

For more information about contributing, and raising PRs or issues, see CONTRIBUTING.md.

Release

See CHANGELOG.md.

License

Licensed under the MIT LICENSE

References

Documentation

Overview

Package apexsigner implements utility that conveniently generate a HTTP Signature.

The APEX security standards supported are

1. APEX L1 - HMAC256

2. APEX L2 - RSA256

The name apexsigner stands for "APEX HTTP Signature Signer". Similar to the HTTP signature (HMAC & RSA) standard defined in IETF, apexsigner generates a HTTP signature with a given set of parameters specified by the API Gateway. The API Gateway will verified the HTTP signature against the corresponding public key uploaded.

Let's start by creating a request object(struct) for apexsigner

type APIParam struct {
	Realm        string `json:"realm"`
	AppID        string `json:"appId"`
	AuthPrefix   string `json:"authPrefix"`
	Secret       string `json:"secret"`
	InvokeURL    string `json:"invokeUrl"`
	SignatureURL string `json:"signatureUrl"`

	HTTPMethod string `json:"httpMethod"`
	Signature  string `json:"signature"`

	PrivateCertFileName string `json:"privateCertFileName"`
	Passphrase          string
	SignatureMethod     string `json:"signatureMethod"`
	Nonce               string `json:"nonce"`
	Timestamp           string `json:"timestamp"`
	Version             string `json:"version"`

	QueryString map[string]interface{} `json:"queryString"`
	FormData    map[string]interface{} `json:"formData"`
}

Preparing the request options

For APEX L1 Signature

The key parameters are the AppID and Secret, which you can retrieved from APEX Community Manager of
your respective tenant. Additionally, please note the difference between InvokeURL and SignatureURL , which
is an internally regconised URL. This inconsistency will be removed in the near future.

requestOpts := APIParam{
		Realm:    "https://portal.example.com,
		AppID: "AppID123",
		AuthPrefix: "apex_lg_l1",
		Secret: "Secret",
		InvokeURL: "https://something.api.gov.sg/v1/resource",
		SignatureURL: ""https://something.api.i.gov.sg/v1/resource""
}

For APEX L2 Signature

The key parameters are the AppID and PrivateCertFileName, which is the file path where you stored your
private key. Please remember to upload the corresponding public key to the App created in APEX Community
Manager, and retrieve its AppID.Same as above, please note the difference between InvokeURL and SignatureURL , which
is an internally regconised URL. This inconsistency will be removed in the near future.

requestOpts := APIParam{
		Realm:    "https://portal.example.com,
		AppID: "AppID123",
		AuthPrefix: "apex_lg_l2",
		Secret: "Secret",
		PrivateCertFileName: "/path/secret.pm",
		Passphrase: "password"
		InvokeURL: "https://something.api.gov.sg/v1/resource",
		SignatureURL: ""https://something.api.i.gov.sg/v1/resource""
}

Using the apexsigner library

apexAuthHeader, err := getSignatureToken(requestOpts)

After getting the Signature Token, just append it to the Http Header's Authorization Scheme

import net/http example

var req *http.Request
req.Header.Add("Authorization", apexAuthHeader)

Example App to show how to invoke the library and pass in the necessary arguments

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL