Autenticação Service Provider
API Key:
Na comunicação do BR-UTM (imagem abaixo), as requisições devem ser autenticadas e autorizadas. Devido à natureza distribuída da arquitetura, não é viável que cada provedor possua sua lógica de autenticação e autorização.
Portando, a solução proposta pela ASTM é a de um servidor de autenticação central onde os provedores obtém tokens OAuth2 codificados e assinados em JWT. O Validator da documentação abaixo checa a validade da assinatura do token, utilizando a chave pública do Auth Server.
Um exemplo de troca de mensagens autenticadas é:
Uso da API Key
Com sua API Key, você pode realizar ações programaticamente no ECO-UTM:
- Insira a sua API Key no header da requisição;
- Insira o
scope
- Insira o
intended_audience
- Em caso de comunicação com outro USS, o preencha com o conteúdo campo
manager
da resposta do DSS.
- Em caso de comunicação com outro USS, o preencha com o conteúdo campo
Validator
Implementação
Código de exemplo para início da implementação do Auth Server e do Validator em Go
Código exemplo
package main
import (
"encoding/json"
"flag"
"log"
"net/http"
"os"
"strings"
"github.com/golang-jwt/jwt"
)
var (
keyFile = flag.String("private_key_file", "auth.key", "OAuth private key file")
publicKeyFile = flag.String("public_key_file", "auth.pem", "OAuth public key file")
)
func verifyToken(token string) (bool, error) {
bytes, err := os.ReadFile(*publicKeyFile)
if err != nil {
log.Panic(err)
}
publicKey, err := jwt.ParseRSAPublicKeyFromPEM(bytes)
if err != nil {
log.Panic(err)
}
parts := strings.Split(token, ".")
err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], publicKey)
if err != nil {
return false, nil
}
return true, nil
}
func main() {
http.HandleFunc("/validate", func(w http.ResponseWriter, r *http.Request) {
tokenString := r.URL.Query().Get("token")
valid, err := verifyToken(tokenString)
if err != nil {
log.Panic(err)
}
log.Println(valid)
})
http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"aud": "aud",
"scope": "scope",
"iss": "iss",
"exp": "exp",
"sub": "sub",
})
// Read private key
bytes, err := os.ReadFile(*keyFile)
if err != nil {
log.Panic(err)
}
privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(bytes)
if err != nil {
log.Panic(err)
}
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString(privateKey)
if err != nil {
log.Panic(err)
}
resp := make(map[string]string)
resp["access_token"] = tokenString
jsonResp, err := json.Marshal(resp)
if err != nil {
log.Fatalf("Error happened in JSON marshal. Err: %s", err)
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write(jsonResp)
return
})
log.Fatal(http.ListenAndServe(":9096", nil))
}
Com o código acima rodando na porta :9096, é necessário criar um Serviço e uma Route no Kong para torná-lo acessível:
Lista de endpoints
A lista completa de endpoints também está disponível neste arquivo OpenAPI e nesta coleção no Insomina.
ECO-UTM
A URL base para os seguintes endpoints é http://montreal.icea.decea.mil.br:64235/
GET | /user-keys/{user-id} |
Aprovar token de autenticação do provedor associado ao usuário
Path Param
intented_audience | user da entetidade de destino da mensagem |
scope | escopo da requisição |
Bearer
token | Bearer token gerado |
Request Body
response = requests.get(
f"{AUTH_URL}/token",
params={
"grant_type": "client_credentials",
"intended_audience": "localhost",
"issuer": "localhost",
"sub": "icea",
"scope": "utm.constraint_management",
"apikey": "brutm",
},
)
Response
200 |
Success |
404 |
User not found |