some more work, still not connected to mqtt tho
parent
383eb2f682
commit
d2170f1adb
|
|
@ -7,7 +7,13 @@
|
|||
#include <QJsonDocument>
|
||||
#include <QSettings>
|
||||
|
||||
#include "qmqtt.h"
|
||||
#include "sigv4utils.h"
|
||||
|
||||
static QByteArray clientId = "8rjhfdlf9jf1suok2jcrltd6v";
|
||||
static QByteArray region = "eu-west-1";
|
||||
//static QByteArray service = "iotdevicegateway";
|
||||
static QByteArray service = "iotdata";
|
||||
|
||||
AWSClient::AWSClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
|
@ -18,6 +24,12 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
|
|||
m_username = settings.value("username").toString();
|
||||
m_accessToken = settings.value("accessToken").toByteArray();
|
||||
m_idToken = settings.value("idToken").toByteArray();
|
||||
m_refreshToken = settings.value("refreshToken").toByteArray();
|
||||
|
||||
m_accessKeyId = settings.value("accessKeyId").toByteArray();
|
||||
m_secretKey = settings.value("secretKey").toByteArray();
|
||||
m_sessionToken = settings.value("sessionToken").toByteArray();
|
||||
|
||||
}
|
||||
|
||||
bool AWSClient::isLoggedIn() const
|
||||
|
|
@ -55,46 +67,46 @@ void AWSClient::login(const QString &username, const QString &password)
|
|||
authParams.insert("PASSWORD", password);
|
||||
|
||||
params.insert("AuthParameters", authParams);
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
|
||||
QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
|
||||
QNetworkReply *reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, &AWSClient::initiateAuthReply);
|
||||
|
||||
qDebug() << "Logging in to AWS as user:" << username;
|
||||
|
||||
QNetworkReply *reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
reply->deleteLater();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "Error logging in to aws:" << reply->error() << reply->errorString();
|
||||
return;
|
||||
}
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Failed to parse AWS login response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
|
||||
m_accessToken = authenticationResult.value("AccessToken").toByteArray();
|
||||
m_idToken = authenticationResult.value("IdToken").toByteArray();
|
||||
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("cloud");
|
||||
settings.setValue("accessToken", m_accessToken);
|
||||
settings.setValue("idToken", m_idToken);
|
||||
settings.setValue("refreshToken", m_refreshToken);
|
||||
|
||||
qDebug() << "AWS login successful" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
emit isLoggedInChanged();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void AWSClient::initiateAuthReply()
|
||||
void AWSClient::getId()
|
||||
{
|
||||
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "Error logging in to aws:" << reply->error() << reply->errorString() << qUtf8Printable(data);
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Failed to parse AWS login response" << error.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
|
||||
|
||||
m_accessToken = authenticationResult.value("AccessToken").toByteArray();
|
||||
m_idToken = authenticationResult.value("IdToken").toByteArray();
|
||||
QSettings settings;
|
||||
settings.beginGroup("cloud");
|
||||
settings.setValue("accessToken", m_accessToken);
|
||||
settings.setValue("idToken", m_idToken);
|
||||
|
||||
qDebug() << "AWS login successful";
|
||||
emit isLoggedInChanged();
|
||||
|
||||
// return; // Why should we call GetId? Ask Luca
|
||||
|
||||
QUrl url("https://cognito-identity.eu-west-1.amazonaws.com/");
|
||||
|
||||
QUrlQuery query;
|
||||
|
|
@ -114,19 +126,174 @@ void AWSClient::initiateAuthReply()
|
|||
params.insert("IdentityPoolId", "eu-west-1:108a174c-5786-40f9-966a-1a0cd33d6801");
|
||||
params.insert("Logins", logins);
|
||||
|
||||
jsonDoc = QJsonDocument::fromVariant(params);
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
|
||||
QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
|
||||
|
||||
reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, &AWSClient::getIdReply);
|
||||
QNetworkReply *reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
reply->deleteLater();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "Error calling GetId" << reply->error() << reply->errorString();
|
||||
return;
|
||||
}
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error parsing json reply for GetId" << error.errorString();
|
||||
return;
|
||||
}
|
||||
QByteArray identityId = jsonDoc.toVariant().toMap().value("IdentityId").toByteArray();
|
||||
|
||||
qDebug() << "Received cognito identity id" << identityId;
|
||||
getCredentialsForIdentity(identityId);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void AWSClient::getIdReply()
|
||||
void AWSClient::getCredentialsForIdentity(const QString &identityId)
|
||||
{
|
||||
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
|
||||
reply->deleteLater();
|
||||
QByteArray data = reply->readAll();
|
||||
qDebug() << "GetID reply" << reply->error() << reply->errorString() << qUtf8Printable(data);
|
||||
QUrl url("https://cognito-identity.eu-west-1.amazonaws.com/");
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("Action", "GetCredentialsForIdentity");
|
||||
query.addQueryItem("Version", "2016-06-30");
|
||||
url.setQuery(query);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-amz-json-1.0");
|
||||
request.setRawHeader("Host", "cognito-identity.eu-west-1.amazonaws.com");
|
||||
request.setRawHeader("X-Amz-Target", "AWSCognitoIdentityService.GetCredentialsForIdentity");
|
||||
|
||||
QVariantMap logins;
|
||||
logins.insert("cognito-idp.eu-west-1.amazonaws.com/eu-west-1_6eX6YjmXr", m_idToken);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("IdentityId", identityId);
|
||||
params.insert("Logins", logins);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
|
||||
QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
|
||||
|
||||
qDebug() << "Calling GetCredentialsForIdentity:" << request.url();
|
||||
qDebug() << "Headers:";
|
||||
foreach (const QByteArray &headerName, request.rawHeaderList()) {
|
||||
qDebug() << headerName << ":" << request.rawHeader(headerName);
|
||||
}
|
||||
qDebug() << "Payload:" << qUtf8Printable(payload);
|
||||
|
||||
QNetworkReply *reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
reply->deleteLater();
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "Error calling GetCredentialsForIdentity" << reply->errorString();
|
||||
return;
|
||||
}
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error parsing JSON reply from GetCredentialsForIdentity" << error.errorString();
|
||||
return;
|
||||
}
|
||||
QVariantMap credentialsMap = jsonDoc.toVariant().toMap().value("Credentials").toMap();
|
||||
|
||||
m_accessKeyId = credentialsMap.value("AccessKeyId").toByteArray();
|
||||
m_secretKey = credentialsMap.value("SecretKey").toByteArray();
|
||||
m_sessionToken = credentialsMap.value("SessionToken").toByteArray();
|
||||
m_expirationDate = QDateTime::fromSecsSinceEpoch(credentialsMap.value("Expiration").toLongLong());
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("cloud");
|
||||
settings.setValue("accessKeyId", m_accessKeyId);
|
||||
settings.setValue("secretKey", m_secretKey);
|
||||
settings.setValue("sessionToken", m_sessionToken);
|
||||
|
||||
qDebug() << "Raw GetCredentialsForIdentity reply:" << qUtf8Printable(data);
|
||||
qDebug() << "GetCredentialsForIdentity reply: \nAccess Key ID:" << m_accessKeyId << "\nSecret Key:" << m_secretKey << "\nsessionkey:" << m_sessionToken << "\nExpiration:" << m_expirationDate;
|
||||
|
||||
postToMQTT();
|
||||
});
|
||||
}
|
||||
|
||||
void AWSClient::connectMQTT()
|
||||
{
|
||||
|
||||
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com";
|
||||
QString uri = "/mqtt";
|
||||
|
||||
QNetworkRequest request(QUrl("wss://" + host + uri));
|
||||
request.setRawHeader("Host", host.toUtf8());
|
||||
|
||||
QByteArray dateTime = SigV4Utils::getCurrentDateTime();
|
||||
// QByteArray canonicalQueryString = SigV4Utils::getCanonicalQueryString(request, m_accessKeyId, m_secretKey, m_sessionToken, region, service, QByteArray());
|
||||
QByteArray canonicalQueryString = SigV4Utils::getCanonicalQueryString(request, m_accessKeyId, m_secretKey, QByteArray(), region, service, QByteArray());
|
||||
|
||||
QString signedRequestUrl = "wss://" + host + uri + '?' + canonicalQueryString;
|
||||
|
||||
qDebug() << "Connecting MQTT to" << signedRequestUrl;
|
||||
|
||||
QMQTT::Client *mqttClient = new QMQTT::Client(signedRequestUrl, QString(clientId), QWebSocketProtocol::VersionLatest, false);
|
||||
mqttClient->setClientId(QString(clientId));
|
||||
mqttClient->setPort(443);
|
||||
mqttClient->setVersion(QMQTT::V3_1_1);
|
||||
|
||||
connect(mqttClient, &QMQTT::Client::connected, this, []{
|
||||
qDebug() << "MQTT connected";
|
||||
});
|
||||
connect(mqttClient, &QMQTT::Client::disconnected, this, []{
|
||||
qDebug() << "MQTT disconnected";
|
||||
});
|
||||
connect(mqttClient, &QMQTT::Client::error, this, [](const QMQTT::ClientError error){
|
||||
qDebug() << "MQTT error" << error;
|
||||
});
|
||||
mqttClient->connectToHost();
|
||||
}
|
||||
|
||||
void AWSClient::postToMQTT()
|
||||
{
|
||||
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com";
|
||||
QString topic = "850593e9-f2ab-4e89-913a-16f848d48867/eu-west-1:88c8b0f1-3f26-46cb-81f3-ccc37dcb543a/";
|
||||
QString path = "/topics/" + topic.toUtf8().toPercentEncoding().toPercentEncoding().toPercentEncoding() + "?qos=0";
|
||||
// QString path1 = "/topics/" + topic.toUtf8().toPercentEncoding().toPercentEncoding() + "?qos=0";
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("message", "Hello box");
|
||||
QByteArray payload = QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact);
|
||||
|
||||
QByteArray dateTime = SigV4Utils::getCurrentDateTime();
|
||||
// dateTime = "20180808T134011Z";
|
||||
|
||||
|
||||
QNetworkRequest request("https://" + host + path);
|
||||
request.setRawHeader("content-type", "application/json");
|
||||
request.setRawHeader("host", host.toUtf8());
|
||||
request.setRawHeader("x-amz-date", dateTime);
|
||||
request.setRawHeader("x-amz-security-token", m_sessionToken);
|
||||
// request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-amz-json-1.0");
|
||||
|
||||
|
||||
QByteArray canonicalRequest = SigV4Utils::getCanonicalRequest(QNetworkAccessManager::PostOperation, request, payload);
|
||||
qDebug() << "canonical request:" << qUtf8Printable(canonicalRequest);
|
||||
QByteArray stringToSign = SigV4Utils::getStringToSign(canonicalRequest, dateTime, region, service);
|
||||
qDebug() << "string to sign:" << stringToSign;
|
||||
QByteArray signature = SigV4Utils::getSignature(stringToSign, m_secretKey, dateTime, region, service);
|
||||
qDebug() << "signature:" << signature;
|
||||
QByteArray authorizeHeader = SigV4Utils::getAuthorizationHeader(m_accessKeyId, dateTime, region, service, request, signature);
|
||||
|
||||
request.setRawHeader("Authorization", authorizeHeader);
|
||||
|
||||
qDebug() << "Posting to MQTT:" << request.url().toString();
|
||||
qDebug() << "HEADERS:";
|
||||
foreach (const QByteArray &headerName, request.rawHeaderList()) {
|
||||
qDebug() << headerName << ":" << request.rawHeader(headerName);
|
||||
}
|
||||
qDebug() << "Payload:" << payload;
|
||||
QNetworkReply *reply = m_nam->post(request, payload);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply]() {
|
||||
reply->deleteLater();
|
||||
qDebug() << "post reply" << reply->readAll();
|
||||
});
|
||||
}
|
||||
|
||||
void AWSClient::fetchDevices()
|
||||
|
|
@ -160,6 +327,9 @@ void AWSClient::fetchDevices()
|
|||
ret.append(d);
|
||||
}
|
||||
emit devicesFetched(ret);
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -168,3 +338,4 @@ QByteArray AWSClient::accessToken() const
|
|||
{
|
||||
return m_accessToken;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QDate>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
struct SRPUser;
|
||||
|
||||
class AWSDevice {
|
||||
public:
|
||||
|
|
@ -28,6 +28,9 @@ public:
|
|||
|
||||
Q_INVOKABLE void fetchDevices();
|
||||
|
||||
Q_INVOKABLE void postToMQTT();
|
||||
Q_INVOKABLE void getId();
|
||||
|
||||
QByteArray accessToken() const;
|
||||
|
||||
signals:
|
||||
|
|
@ -35,9 +38,9 @@ signals:
|
|||
|
||||
void devicesFetched(QList<AWSDevice> devices);
|
||||
|
||||
private slots:
|
||||
void initiateAuthReply();
|
||||
void getIdReply();
|
||||
private:
|
||||
void getCredentialsForIdentity(const QString &identityId);
|
||||
void connectMQTT();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_nam = nullptr;
|
||||
|
|
@ -45,6 +48,12 @@ private:
|
|||
QString m_username;
|
||||
QByteArray m_accessToken;
|
||||
QByteArray m_idToken;
|
||||
QByteArray m_refreshToken;
|
||||
|
||||
QByteArray m_accessKeyId;
|
||||
QByteArray m_secretKey;
|
||||
QByteArray m_sessionToken;
|
||||
QDateTime m_expirationDate;
|
||||
};
|
||||
|
||||
#endif // AWSCLIENT_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
#include "sigv4utils.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QCryptographicHash>
|
||||
#include <QMessageAuthenticationCode>
|
||||
#include <QtDebug>
|
||||
#include <QUrlQuery>
|
||||
#include <QList>
|
||||
|
||||
SigV4Utils::SigV4Utils()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCurrentDateTime()
|
||||
{
|
||||
return QDateTime::currentDateTime().toUTC().toString("yyyyMMddThhmmssZ").toUtf8();
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCanonicalQueryString(const QNetworkRequest &request, const QByteArray &accessKeyId, const QByteArray &secretAccessKey, const QByteArray &sessionToken, const QByteArray ®ion, const QByteArray &service, const QByteArray &payload)
|
||||
{
|
||||
QByteArray algorithm = "AWS4-HMAC-SHA256";
|
||||
QByteArray dateTime = getCurrentDateTime();
|
||||
QByteArray credentialScope = getCredentialScope(algorithm, dateTime, region, service);
|
||||
|
||||
QByteArray canonicalQueryString;
|
||||
canonicalQueryString += "X-Amz-Algorithm=AWS4-HMAC-SHA256";
|
||||
canonicalQueryString += "&X-Amz-Credential=" + QByteArray(accessKeyId + '/' + credentialScope).toPercentEncoding();
|
||||
canonicalQueryString += "&X-Amz-Date=" + dateTime;
|
||||
if (request.rawHeaderList().count() > 0){
|
||||
canonicalQueryString += "&X-Amz-SignedHeaders=" + request.rawHeaderList().join(';').toLower();
|
||||
}
|
||||
|
||||
QByteArray canonicalRequest = getCanonicalRequest(QNetworkAccessManager::GetOperation, request, payload);
|
||||
|
||||
QByteArray stringToSign = getStringToSign(canonicalRequest, dateTime, region, service);
|
||||
QByteArray signature = getSignature(stringToSign, secretAccessKey, dateTime, region, service);
|
||||
|
||||
canonicalQueryString += "&X-Amz-Signature=" + signature;
|
||||
|
||||
if (!sessionToken.isEmpty()) {
|
||||
canonicalQueryString += "&X-Amz-Security-Token=" + sessionToken.toPercentEncoding();
|
||||
}
|
||||
|
||||
return canonicalQueryString;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getSignatureKey(const QByteArray &key, const QByteArray &date, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
|
||||
return QMessageAuthenticationCode::hash("aws4_request",
|
||||
QMessageAuthenticationCode::hash(service,
|
||||
QMessageAuthenticationCode::hash(region,
|
||||
QMessageAuthenticationCode::hash(date, "AWS4"+key,
|
||||
hashAlgorithm), hashAlgorithm), hashAlgorithm), hashAlgorithm);
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCanonicalRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload)
|
||||
{
|
||||
QByteArray canonicalRequest;
|
||||
|
||||
QByteArray method;
|
||||
switch (operation) {
|
||||
case QNetworkAccessManager::GetOperation:
|
||||
method = "GET";
|
||||
break;
|
||||
case QNetworkAccessManager::PostOperation:
|
||||
method = "POST";
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT_X(false, "Network operation not implemented", "SigV4Utils");
|
||||
}
|
||||
QByteArray uri = request.url().path().toUtf8();
|
||||
QUrlQuery query(request.url());
|
||||
QList<QPair<QString, QString> > queryItems = query.queryItems();
|
||||
QStringList queryItemStrings;
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
QPair<QString, QString> queryItem = queryItems.at(i);
|
||||
queryItemStrings.append(queryItem.first + '=' + queryItem.second);
|
||||
}
|
||||
queryItemStrings.sort(Qt::CaseInsensitive);
|
||||
|
||||
QByteArray canonicalQueryString = queryItemStrings.join('&').toUtf8();
|
||||
|
||||
QByteArray canonicalHeaders;
|
||||
foreach(const QByteArray &headerName, request.rawHeaderList()) {
|
||||
canonicalHeaders += headerName.toLower() + ':' + request.rawHeader(headerName) + '\n';
|
||||
}
|
||||
|
||||
QByteArray payloadHash = QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
|
||||
|
||||
canonicalRequest = method + '\n' + uri + '\n' + canonicalQueryString + '\n' + canonicalHeaders + '\n' + request.rawHeaderList().join(';').toLower() + '\n' + payloadHash;
|
||||
return canonicalRequest;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCredentialScope(const QByteArray &algorithm, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
QByteArray credentialScope = dateTime.left(8) + '/' + region + '/' + service + "/aws4_request";
|
||||
return credentialScope;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getStringToSign(const QByteArray &canonicalRequest, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
QByteArray algorithm = "AWS4-HMAC-SHA256";
|
||||
QByteArray credentialScope = getCredentialScope(algorithm, dateTime, region, service);
|
||||
|
||||
QByteArray stringToSign = algorithm + '\n' + dateTime + '\n' + credentialScope + '\n' + QCryptographicHash::hash(canonicalRequest, QCryptographicHash::Sha256).toHex();
|
||||
return stringToSign;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getSignature(const QByteArray &stringToSign, const QByteArray &secretAccessKey, const QByteArray &dateTime, const QString ®ion, const QString &service)
|
||||
{
|
||||
QByteArray signingKey = getSignatureKey(secretAccessKey, dateTime.left(8), region.toUtf8(), service.toUtf8());
|
||||
QByteArray signature = QMessageAuthenticationCode::hash(stringToSign, signingKey, QCryptographicHash::Sha256).toHex();
|
||||
return signature;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getAuthorizationHeader(const QByteArray &accessKeyId, const QByteArray &dateTime, const QString ®ion, const QString &service, const QNetworkRequest &request, const QByteArray &signature)
|
||||
{
|
||||
QByteArray authHeader = "AWS4-HMAC-SHA256 Credential=" + accessKeyId + '/' + dateTime.left(8) + '/' + region.toUtf8() + '/' + service.toUtf8() + '/' + "aws4_request, SignedHeaders=" + request.rawHeaderList().join(';').toLower() + ", Signature=" + signature;
|
||||
return authHeader;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef SIGV4UTILS_H
|
||||
#define SIGV4UTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
class SigV4Utils
|
||||
{
|
||||
public:
|
||||
SigV4Utils();
|
||||
|
||||
static QByteArray getCurrentDateTime();
|
||||
|
||||
|
||||
static QByteArray getCanonicalQueryString(const QNetworkRequest &request, const QByteArray &accessKeyId, const QByteArray &secretAccessKey, const QByteArray &sessionToken, const QByteArray ®ion, const QByteArray &service, const QByteArray &payload);
|
||||
static QByteArray getCanonicalRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload);
|
||||
static QByteArray getCanonicalHeaders(const QNetworkRequest &request);
|
||||
static QByteArray getCredentialScope(const QByteArray &algorithm, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getStringToSign(const QByteArray &canonicalRequest, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getSignatureKey(const QByteArray &key, const QByteArray &date, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getSignature(const QByteArray &stringToSign, const QByteArray &secretAccessKey, const QByteArray &dateTime, const QString ®ion, const QString &service);
|
||||
static QByteArray getAuthorizationHeader(const QByteArray &accessKeyId, const QByteArray &dateTime, const QString ®ion, const QString &service, const QNetworkRequest &request, const QByteArray &signature);
|
||||
|
||||
};
|
||||
|
||||
#endif // SIGV4UTILS_H
|
||||
|
|
@ -269,7 +269,7 @@ void JsonRpcClient::sendRequest(const QVariantMap &request)
|
|||
{
|
||||
QVariantMap newRequest = request;
|
||||
newRequest.insert("token", m_token);
|
||||
qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson());
|
||||
// qDebug() << "Sending request" << qUtf8Printable(QJsonDocument::fromVariant(newRequest).toJson());
|
||||
m_connection->sendData(QJsonDocument::fromVariant(newRequest).toJson(QJsonDocument::Compact) + "\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ include(../config.pri)
|
|||
}
|
||||
DEFINES += QT_STATIC
|
||||
include(../qmqtt/src/mqtt/mqtt.pri)
|
||||
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
|
||||
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \
|
||||
connection/sigv4utils.h
|
||||
|
||||
QT -= gui
|
||||
QT += network websockets bluetooth
|
||||
|
|
@ -77,7 +78,8 @@ SOURCES += \
|
|||
ruletemplates/stateevaluatortemplate.cpp \
|
||||
ruletemplates/statedescriptortemplate.cpp \
|
||||
discovery/bluetoothservicediscovery.cpp \
|
||||
connection/cloudtransport.cpp
|
||||
connection/cloudtransport.cpp \
|
||||
connection/sigv4utils.cpp
|
||||
|
||||
HEADERS += \
|
||||
engine.h \
|
||||
|
|
|
|||
|
|
@ -39,5 +39,16 @@ Page {
|
|||
Engine.awsClient.login(usernameTextField.text, passwordTextField.text);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: "GetId"
|
||||
onClicked: Engine.awsClient.getId();
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: "Post to MQTT"
|
||||
onClicked: Engine.awsClient.postToMQTT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ Page {
|
|||
ListElement { iconSource: "../images/network-vpn.svg"; text: qsTr("Manual connection"); page: "ManualConnectPage.qml" }
|
||||
ListElement { iconSource: "../images/bluetooth.svg"; text: qsTr("Wireless setup"); page: "BluetoothDiscoveryPage.qml"; }
|
||||
ListElement { iconSource: "../images/cloud.svg"; text: qsTr("Cloud login"); page: "CloudLoginPage.qml" }
|
||||
ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "AppSettingsPage.qml" }
|
||||
ListElement { iconSource: "../images/stock_application.svg"; text: qsTr("App settings"); page: "../AppSettingsPage.qml" }
|
||||
}
|
||||
onClicked: {
|
||||
pageStack.push(model.get(index).page);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <QtOpenGL/qgl.h>
|
||||
#endif
|
||||
|
||||
#include "libmea-core.h"
|
||||
#include "libnymea-app-core.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ INCLUDEPATH += ../../nymea-app/ \
|
|||
../../libnymea-common/ \
|
||||
../../libnymea-app-core/
|
||||
|
||||
LIBS += -L$$top_builddir/libmea-core/ -lmea-core \
|
||||
-L$$top_builddir/libnymea-common/ -lnymea-common
|
||||
LIBS += -L$$top_builddir/libnymea-app-core/ -lnymea-app-core \
|
||||
-L$$top_builddir/libnymea-common/ -lnymea-common \
|
||||
-lavahi-common -lavahi-client
|
||||
win32:Debug:LIBS += -L$$top_builddir/libmea-core/debug \
|
||||
-L$$top_builddir/libnymea-common/debug
|
||||
win32:Release:LIBS += -L$$top_builddir/libmea-core/release \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = testrunner
|
||||
SUBDIRS = testrunner unit
|
||||
|
|
|
|||
Loading…
Reference in New Issue