Add program to generate long lived tokens. Use python to get a token directly.
This commit is contained in:
parent
bfb110d061
commit
c76ff553cc
|
|
@ -12,6 +12,7 @@ else()
|
|||
endif()
|
||||
|
||||
find_package(jwt-cpp)
|
||||
find_package(argparse)
|
||||
find_package(OpenSSL)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
|
@ -23,3 +24,11 @@ target_include_directories(j7s-plugin PUBLIC
|
|||
${jwt-cpp_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(j7s-plugin OpenSSL::Crypto)
|
||||
|
||||
add_executable(gen-token src/gen-token.cpp)
|
||||
target_include_directories(gen-token PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
${jwt-cpp_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(gen-token OpenSSL::Crypto argparse::argparse)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ Authentication using JWTs for the mosquitto mqtt broker.
|
|||
|
||||
## Dependencies
|
||||
```
|
||||
sudo apt install mosquitto-dev g++ cmake libmosquitto-dev mosquitto-clients
|
||||
sudo apt install openssl libssl-dev
|
||||
sudo apt install mosquitto-dev g++ cmake libmosquitto-dev mosquitto-clients openssl libssl-dev
|
||||
```
|
||||
|
||||
## Generating offline keys
|
||||
ssh-keygen -t rsa -b 4096 -m PEM -f priv.key
|
||||
rm priv.key.pub
|
||||
openssl rsa -in priv.key -pubout -outform PEM -out pub.key
|
||||
|
|
|
|||
|
|
@ -16,6 +16,19 @@ list (APPEND EXTRA_CMAKE_ARGS
|
|||
-Djwt-cpp_DIR=${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp -Djwt-cpp_INCLUDE_DIR=${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp/include
|
||||
)
|
||||
|
||||
list(APPEND DEPENDENCIES ep_argparse)
|
||||
ExternalProject_Add(ep_argparse
|
||||
PREFIX ep_argparse
|
||||
GIT_REPOSITORY "https://github.com/p-ranav/argparse.git"
|
||||
GIT_TAG "v2.2"
|
||||
GIT_SHALLOW "True"
|
||||
CMAKE_ARGS -DARGPARSE_CMAKE_FILES_INSTALL_DIR=${CMAKE_CURRENT_BINARY_DIR}/argparse -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/argparse
|
||||
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/argparse
|
||||
)
|
||||
list (APPEND EXTRA_CMAKE_ARGS
|
||||
-Dargparse_DIR=${CMAKE_CURRENT_BINARY_DIR}/argparse
|
||||
)
|
||||
|
||||
ExternalProject_Add (ep_j7s-mosquitto-plugin
|
||||
PREFIX ep_j7s-mosquitto-plugin
|
||||
DEPENDS ${DEPENDENCIES}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2022 James Pace
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <argparse/argparse.hpp>
|
||||
#include <jwt-cpp/jwt.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
std::optional<std::string> read_key(const std::string& key_file);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argparse::ArgumentParser program("gen-token", "0.0.0");
|
||||
|
||||
program.add_argument("--pub-key")
|
||||
.required()
|
||||
.help("Pub key of signer.");
|
||||
program.add_argument("--priv-key")
|
||||
.required()
|
||||
.help("Private key of signer.");
|
||||
program.add_argument("--issuer")
|
||||
.required()
|
||||
.help("Issuer to assign to signed key.");
|
||||
program.add_argument("--username")
|
||||
.required()
|
||||
.help("Username assigned to key.");
|
||||
program.add_argument("--valid-days")
|
||||
.required()
|
||||
.help("Days from now until the token will be valid.");
|
||||
program.add_argument("--can-read")
|
||||
.help("holder can read")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
program.add_argument("--can-write")
|
||||
.help("holder can write")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
try
|
||||
{
|
||||
program.parse_args(argc, argv);
|
||||
}
|
||||
catch (const std::runtime_error & err)
|
||||
{
|
||||
std::cerr << err.what() << std::endl;
|
||||
std::cerr << program;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto priv_key_file = program.get<std::string>("--priv-key");
|
||||
const auto priv_key = read_key(std::filesystem::absolute(priv_key_file));
|
||||
const auto pub_key_file = program.get<std::string>("--pub-key");
|
||||
const auto pub_key = read_key(std::filesystem::absolute(pub_key_file));
|
||||
|
||||
if(not pub_key or not priv_key)
|
||||
{
|
||||
std::cerr << "Could not open key!" << std::endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
const std::string can_read = program.get<bool>("--can-read") ? "true" : "false";
|
||||
const std::string can_write = program.get<bool>("--can-write") ? "true" : "false";
|
||||
|
||||
const auto expr_time = std::chrono::system_clock::now() +
|
||||
std::chrono::days(std::stoi(program.get<std::string>("--valid-days")));
|
||||
|
||||
const auto token = jwt::create()
|
||||
.set_type("JWT")
|
||||
.set_issuer(program.get<std::string>("--issuer"))
|
||||
.set_payload_claim("upn", jwt::claim(program.get<std::string>("--username")))
|
||||
.set_payload_claim("mqtt-write", jwt::claim(can_read))
|
||||
.set_payload_claim("mqtt-read", jwt::claim(can_write))
|
||||
.set_expires_at(expr_time)
|
||||
.sign(jwt::algorithm::rs256(pub_key.value(), priv_key.value(), "", ""));
|
||||
|
||||
std::cout << token;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::optional<std::string> read_key(const std::string& key_file)
|
||||
{
|
||||
// Read key from file.
|
||||
std::ifstream key_stream(key_file, std::ios::binary);
|
||||
if(not key_stream)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << key_stream.rdbuf();
|
||||
return ss.str();
|
||||
}
|
||||
|
|
@ -1,12 +1,17 @@
|
|||
per_listener_settings true
|
||||
log_type all
|
||||
|
||||
listener 8082
|
||||
protocol websockets
|
||||
|
||||
listener 8081
|
||||
protocol mqtt
|
||||
|
||||
log_type all
|
||||
allow_anonymous true
|
||||
|
||||
allow_anonymous false
|
||||
auth_plugin /home/jimmy/Develop/mosquitto-plugin/build/libj7s-plugin.so
|
||||
auth_opt_issuer https://auth.jpace121.net/realms/jpace121-main
|
||||
auth_opt_public_key /home/jimmy/Develop/mosquitto-plugin/test/key.pem
|
||||
|
||||
listener 8081
|
||||
protocol mqtt
|
||||
allow_anonymous false
|
||||
auth_plugin /home/jimmy/Develop/mosquitto-plugin/build/libj7s-plugin.so
|
||||
auth_opt_issuer https://auth.jpace121.net/realms/jpace121-main
|
||||
auth_opt_public_key /home/jimmy/Develop/mosquitto-plugin/test/key.pem
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import requests
|
||||
import json
|
||||
import time
|
||||
import paho.mqtt.client
|
||||
import time
|
||||
|
||||
# RESULT=`curl --cacert ./ca.pem --cert jimmy-client.pem --key jimmy-client-key.pem --data "grant_type=password&client_id=test&username=jimmy&password=1234" https://nginx-test.internal.jpace121.net:8443/realms/master/protocol/openid-connect/token`
|
||||
|
||||
s = requests.Session()
|
||||
s.verify = "/home/jimmy/Develop/mosquitto-plugin/test/ca.pem"
|
||||
s.cert = ("/home/jimmy/Develop/keycloak/jimmy-client.pem", "/home/jimmy/Develop/keycloak/jimmy-client-key.pem")
|
||||
|
||||
|
||||
# Get urls.
|
||||
print("Before get.")
|
||||
well_known = s.get("https://nginx-test.internal.jpace121.net:8443/realms/jpace121-main/.well-known/openid-configuration", ).json()
|
||||
print("After get.")
|
||||
token_url = well_known['token_endpoint']
|
||||
# Override for now, url doesn't include port...
|
||||
token_url = "https://nginx-test.internal.jpace121.net:8443/realms/jpace121-main/protocol/openid-connect/token"
|
||||
# RESULT=`curl --cacert ./ca.pem --cert jimmy-client.pem --key jimmy-client-key.pem --data "grant_type=password&client_id=mqtt&username=jimmy&password=1234" https://nginx-test.internal.jpace121.net:8443/realms/jpace121-main/protocol/openid-connect/token`
|
||||
|
||||
|
||||
data = {"grant_type" : "password", "client_id" : "mqtt", "username" : "jimmy", "password": "1234"}
|
||||
|
||||
# Request token.
|
||||
r = s.post(token_url, data=data)
|
||||
token = r.json()['access_token']
|
||||
|
||||
client = paho.mqtt.client.Client(protocol=paho.mqtt.client.MQTTv5,
|
||||
transport="tcp")
|
||||
client.username_pw_set("jimmy", password=token)
|
||||
client.connect("localhost", port=8081)
|
||||
|
||||
print("Waiting on connection.")
|
||||
time.sleep(20)
|
||||
Loading…
Reference in New Issue